2012-08-23 10 views
36

मैं एक ऐसी रिपोर्ट जेनरेट करने के लिए बुनाई का उपयोग करने की कोशिश कर रहा हूं जो डेटा सेट के विभिन्न सबसेट पर विश्लेषण का एक ही सेट करता है। प्रोजेक्ट में दो आरएमडी फाइलें हैं: पहली फ़ाइल एक मास्टर दस्तावेज़ है जो वर्कस्पेस और दस्तावेज़ को सेट करता है, दूसरी फ़ाइल में केवल ऐसे भाग होते हैं जो विश्लेषण करते हैं और संबंधित आंकड़े उत्पन्न करते हैं।आर बुनाई: चंक लेबल को प्रोग्रामेटिक रूप से संशोधित करना संभव है?

मैं जो करना चाहता हूं वह मास्टर फ़ाइल को बुनाई है, जो प्रत्येक डेटा सबसेट के लिए दूसरी फ़ाइल को कॉल करेगा और परिणामों को एक दस्तावेज़ में शामिल करेगा। नीचे एक साधारण उदाहरण है।

मास्टर दस्तावेज़:

# My report 

```{r} 
library(iterators) 
data(mtcars) 
``` 

```{r create-iterator} 
cyl.i <- iter(unique(mtcars$cyl)) 
``` 

## Generate report for each level of cylinder variable 
```{r cyl4-report, child='analysis-template.Rmd'} 
``` 

```{r cyl6-report, child='analysis-template.Rmd'} 
``` 

```{r cyl8-report, child='analysis-template.Rmd'} 
``` 

विश्लेषण-template.Rmd:

```{r, results='asis'} 
cur.cyl <- nextElem(cyl.i) 
cat("###", cur.cyl) 
``` 

```{r mpg-histogram} 
hist(mtcars$mpg[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders")) 
``` 

```{r weight-histogam} 
hist(mtcars$wt[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders")) 
``` 

समस्या knitr गैर-अद्वितीय हिस्सा लेबल के लिए अनुमति नहीं देता है, तो बुनाई जब analysis-template.Rmd दूसरा कहा जाता है विफल रहता है पहर। इस समस्या को अज्ञात हिस्सों को छोड़कर टाला जा सकता है क्योंकि अद्वितीय लेबल स्वचालित रूप से जेनरेट किए जाएंगे। यह आदर्श नहीं है, हालांकि, क्योंकि मैं निर्यातित भूखंडों के लिए सूचनात्मक फ़ाइल नाम बनाने के लिए खंड लेबल का उपयोग करना चाहता हूं।


एक संभावित समाधान एक साधारण समारोह है कि हिस्सा लेबल करने के लिए वर्तमान सिलेंडर संलग्न कर देता है का उपयोग कर होगा:

```r{paste('cur-label', cyl, sep = "-")} 
``` 

लेकिन यह प्रकट नहीं होता है कि knitr हिस्सा लेबल की स्थिति में एक अभिव्यक्ति का मूल्यांकन करेंगे ।


मैं भी एक कस्टम chunk hook कि मौजूदा हिस्सा के लेबल संशोधित उपयोग करने की कोशिश:

knit_hooks$set(cyl.suffix = function(before, options, envir) { 
    if (before) options$label <- "new-label" 
}) 

लेकिन हिस्सा लेबल उत्पन्न भूखंडों के लिए फ़ाइल नाम को प्रभावित नहीं किया बदल रहा है, तो मुझे नहीं लगता था knitr नए लेबल का उपयोग कर रहा था।


चंक लेबल को बदलने के तरीके पर कोई विचार, तो एक ही बच्चे दस्तावेज़ को कई बार बुलाया जा सकता है? या शायद इसे पूरा करने के लिए एक वैकल्पिक रणनीति?

उत्तर

35

इस पोस्ट में आने वाले किसी और के लिए, मैं यह इंगित करना चाहता था कि @Yihui ने knit_expand() फ़ंक्शन के परिचय के साथ knitr 1.0 में इस प्रश्न के लिए formal solution प्रदान किया है। यह बहुत अच्छा काम करता है और वास्तव में मेरे वर्कफ़्लो को सरल बना देता है।

उदाहरण के लिए, निम्नलिखित mtcars$cyl के हर स्तर के लिए नीचे दिए गए टेम्प्लेट स्क्रिप्ट पर कार्रवाई करेंगे, हर बार अपने वर्तमान मूल्य के साथ {{ncyl}} के सभी उदाहरणों (टेम्पलेट में) की जगह:

# My report 

```{r} 
data(mtcars) 
cyl.levels <- unique(mtcars$cyl) 
``` 

## Generate report for each level of cylinder variable 
```{r, include=FALSE} 
src <- lapply(cyl.levels, function(ncyl) knit_expand(file = "template.Rmd")) 
``` 

`r knit(text = unlist(src))` 

टेम्पलेट:

```{r, results='asis'} 
cat("### {{ncyl}} cylinders") 
``` 

```{r mpg-histogram-{{ncyl}}cyl} 
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
    main = paste({{ncyl}}, "cylinders")) 
``` 

```{r weight-histogam-{{ncyl}}cyl} 
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
    main = paste({{ncyl}}, "cylinders")) 
``` 
+0

मैंने इस दृष्टिकोण का उपयोग किया है, लेकिन ध्यान दिया है कि टेम्पलेट परिणामों में 'echo = FALSE' का उपयोग करके कोड संसाधित नहीं किया जा रहा है। क्या आपने वही व्यवहार देखा है? –

+0

** संपादित करें **: मैंने ** बुकडाउन ** पैकेज के साथ इस दृष्टिकोण का उपयोग किया है और देखा है कि टेम्पलेट परिणामों में 'परिणाम =' asis'' और 'echo = FALSE' का उपयोग करके कोड संसाधित नहीं किया जा रहा है। समाधान प्रत्येक आउटपुट को एक अलग कोड खंड में रखना है। –

14

यदि आप अपने ** नामहीन में सभी भाग बनाते हैं, यानी ```{r} यह काम करता है। यह, ज़ाहिर है, बहुत ही सुरुचिपूर्ण नहीं है, लेकिन वर्तमान खंड के लेबल को बदलने से आपको रोकने में दो मुद्दे हैं:

  1. कोड ब्लॉक निष्पादित होने से पहले एक फ़ाइल को पार्स किया जाता है। किसी भी कोड को निष्पादित करने से पहले या कस्टम हुक कहने से पहले पार्सर पहले ही डुप्लिकेट लेबल का पता लगाता है।
  2. खंड विकल्प (इंक। लेबल) को हुक कहा जाने से पहले संसाधित किया जाता है (तार्किक: यह एक विकल्प है जो एक हुक ट्रिगर करता है), इसलिए हुक लेबल को और नहीं बदल सकता है।

तथ्य यह है कि अज्ञात ब्लॉक काम करते हैं कि आंतरिक रूप से उन्हें लेबल unnamed-chunk- + खंड संख्या मिलती है।

ब्लॉक में डुप्लिकेट नाम नहीं हो सकते हैं क्योंकि आंतरिक रूप से उन्हें लेबल द्वारा संदर्भित किया जाता है। डुप्लिकेट नामों के साथ सभी भागों में खंड संख्या को जोड़ने के लिए एक फिक्स हो सकता है।या उन्हें लेबल के बजाय खंड संख्या द्वारा संदर्भित करने के लिए, लेकिन ऐसा लगता है कि मुझे एक बड़ा परिवर्तन लगता है।

+7

आपकी समझ बिल्कुल सही है, और यह एक दृढ़ मामला है कि बुनाई को कुछ बदलावों की आवश्यकता है। मैं अब आपके पुल अनुरोध को देख रहा हूं। धन्यवाद! –

+0

@Rolo, बुनाई के आंतरिक कार्यकलापों की आपकी व्याख्या बहुत उपयोगी थी। और मैं वास्तव में लिखने का समय लेता हूं [आपके समाधान को लागू करने वाला कोड] (https://github.com/yihui/knitr/issues/368)। @Yihui, क्या आपको लगता है कि आप इस परिवर्तन को शामिल करेंगे? यह 9 0% जो मैं पूरा करने की कोशिश कर रहा था उसे संबोधित करता हूं और संशोधित खंड लेबल को छोड़कर आरएमडी फाइलों की प्रतियों को बनाए रखने के लिए इसे अनावश्यक बना देता है। आदर्श समाधान 'के लिए (मैं अद्वितीय (mtcars $ cyl)) knit_child ("विश्लेषण-टेम्पलेट.आरएमडी", label.suffix = i)', जैसे कि यह व्यवहार्य था, के लिए कुछ की अनुमति देगा। – aaronwolen

+1

हाँ मुझे लगता है कि मैं पुल अनुरोध स्वीकार करता हूं; बस मुझे कुछ और मिनट दें क्योंकि मेरे पास अभी भी कुछ वैकल्पिक समाधान हैं। इस समस्या को हल करना आसान है लेकिन यह तय करना मुश्किल है कि किस समाधान का उपयोग करना है। –

संबंधित मुद्दे