2012-06-10 14 views
47

मेरे पास अक्सर मुख्य आर मार्कडाउन फ़ाइल या बुनाई लाटेक्स फ़ाइल होती है जहां मैं source कुछ अन्य आर फ़ाइल (उदा।, डेटा प्रोसेसिंग के लिए)। हालांकि, मैं सोच रहा था कि कुछ मामलों में यह सोर्स की गई फाइलें अपने स्वयं के पुनरुत्पादित दस्तावेज़ होने के लिए फायदेमंद होंगी (उदाहरण के लिए, एक आर मार्कडाउन फ़ाइल जिसमें न केवल डेटा प्रोसेसिंग के लिए कमांड शामिल हैं, बल्कि एक पुनरुत्पादित दस्तावेज़ भी उत्पन्न करता है जो डेटा प्रोसेसिंग को बताता है निर्णय)।आर मार्कडाउन फ़ाइल जैसे स्रोत 'स्रोत (' myfile.r ') स्रोत कैसे करें?

इस प्रकार, मैं अपने मुख्य आर मार्कडाउन फ़ाइल में source('myfile.rmd') जैसे कमांड रखना चाहता हूं। जो myfile.rmd के आर कोड भाग के अंदर सभी आर कोड निकालें और स्रोत करेगा। बेशक, यह एक त्रुटि को जन्म देता है।

निम्न आदेश काम करता है:

```{r message=FALSE, results='hide'} 
knit('myfile.rmd', tangle=TRUE) 
source('myfile.R') 
``` 

जहां results='hide' अगर उत्पादन वांछित था लोप हो सकता है। यानी, knitr myfile.rmd से myfile.R में आर कोड आउटपुट करता है।

हालांकि, यह सही नहीं लगता है:

  • यह एक अतिरिक्त फ़ाइल
  • यह अगर प्रदर्शन पर नियंत्रण की आवश्यकता है अपने आप कोड हिस्सा में प्रदर्शित करने की जरूरत के निर्माण में परिणाम है।
  • यह source(...) के रूप में सुरुचिपूर्ण नहीं है।

इस प्रकार मेरे सवाल: वहाँ एक अनुसंधान Markdown फ़ाइल के आर कोड सोर्सिंग का एक और अधिक सुंदर तरीका है?

+0

मैं वास्तव में एक बहुत कठिन समय अपने प्रश्न (मैं इसे कई बार पढ़ा) समझ आ रही है। आप अन्य आर स्क्रिप्ट को आसानी से 'आरएमडी' फाइल में स्रोत कर सकते हैं। लेकिन आप बुनाई वाली फाइल में अन्य 'मार्कडाउन' फ़ाइलों में भी स्रोत बनाना चाहते हैं? – Maiasaura

+3

मैं आर मार्कडाउन फ़ाइलों (यानी, * .rmd) में आर कोड भाग के अंदर आर कोड को स्रोत करना चाहता हूं? मैंने चीजों को स्पष्ट करने की कोशिश करने के लिए प्रश्न को थोड़ा सा संपादित किया है। –

+0

लेटेक्स में 'शामिल' की रेखाओं के साथ कुछ। यदि मार्कडाउन अन्य मार्कडाउन दस्तावेज़ों को शामिल करने का समर्थन करता है, तो ऐसा फ़ंक्शन बनाने के लिए अपेक्षाकृत आसान होना चाहिए। –

उत्तर

24

ऐसा लगता है कि आप एक लाइनर की तलाश में हैं। इसे अपने .Rprofile में डालने के बारे में कैसे?

ksource <- function(x, ...) { 
    library(knitr) 
    source(purl(x, output = tempfile()), ...) 
} 

हालांकि, मुझे समझ नहीं आता क्यों तुम आरएमडी में कोड में ही फाइल source() करना चाहते हैं। मेरा मतलब है knit() इस दस्तावेज़ में सभी कोड चलाएगा, और यदि आप कोड निकालते हैं और इसे एक खंड में चलाते हैं, तो यह कोड दो बार चलाया जाएगा जब आप knit() इस दस्तावेज़ (आप स्वयं को अपने अंदर चलाएं)। दो कार्य अलग होना चाहिए।

यदि आप वास्तव में सभी कोड चलाने के लिए चाहते हैं, तो RStudio ने इसे काफी आसान बना दिया है: Ctrl + Shift + R।यह मूल रूप से दृश्य के पीछे purl() और source() पर कॉल करता है।

+3

हाय @ यहुई मुझे लगता है कि यह सहायक है क्योंकि कभी-कभी आपका विश्लेषण छोटी लिपियों में व्यवस्थित किया जा सकता है, लेकिन आपकी रिपोर्ट में आप पूरी पाइपलाइन के लिए कोड रखना चाहते हैं। – lucacerone

+4

तो यहां उपयोग का मामला यह है कि आप सभी कोड लिखना चाहते हैं और इसे अत्यधिक दस्तावेज और समझाया गया है, लेकिन कोड किसी अन्य स्क्रिप्ट द्वारा चलाया जाता है। –

+2

@ ब्रैश एक्वालिब्रियम यह कोड चलाने के लिए 'स्रोत()' या 'knitr :: knit()' का उपयोग करने का विषय है। मुझे पता है कि लोग बाद वाले लोगों से कम परिचित हैं, लेकिन 'purl() 'विश्वसनीय नहीं है। आपको चेतावनी दी गई है: https://github.com/yihui/knitr/pull/812#issuecomment-53088636 –

2

तुम सिर्फ बाद कोड मुझे लगता है कि इन पंक्तियों के साथ कुछ काम करना चाहिए रहे हैं:

  1. कोड हिस्सा लगता है, लाइनों के लिए खोज readLines
  2. उपयोग grep साथ markdown/आर फ़ाइल पढ़ें कि उदाहरण के लिए <<< के साथ शुरू
  3. उद्देश्य यह है कि मूल लाइनों writeLines का उपयोग कर एक अस्थायी फ़ाइल के लिए एक ही कोड
  4. डंप इसे पाने के लिए शामिल की
  5. लें सबसेट
  6. स्रोत अपने अनुसंधान सत्र

एक समारोह में इस रैपिंग आपको क्या चाहिए तुम्हें देना चाहिए में इस फ़ाइल।

+1

धन्यवाद, मुझे लगता है कि काम करेगा। हालांकि, पहले चार अंक स्वेच्छा के लिए विश्वसनीय तरीके से स्टैंगल पहले से ही करते हैं और क्या बुनाई में 'बुनाई' 'myfile.rmd', tangle = TRUE) करता है। मुझे लगता है कि मैं एक लाइनर की तलाश में हूं कि दोनों उलझन और स्रोत और आदर्श रूप से कोई फाइल नहीं बनाते हैं। –

+0

एक बार जब आप इसे किसी फ़ंक्शन में लपेट लेते हैं तो यह एक ऑनलाइनर बन जाता है;)। आप एक फ़ाइल की नकल करने के लिए 'textConnection' का उपयोग कर सकते हैं, और उस से स्रोत का उपयोग कर सकते हैं। यह एक फ़ाइल बनाई जा रही से बचने के लिए होगा। –

+0

हां। 'textConnection' देखने के लिए जगह हो सकती है। –

13

फैक्टर एक अलग आर फ़ाइल में आम कोड बाहर, और फिर स्रोत प्रत्येक आरएमडी में है कि आर फ़ाइल फ़ाइल में यह चाहते हैं।

तो उदाहरण के लिए मान लीजिए कि मैं दो रिपोर्टों मैं बनाने के लिए, फ्लू फैलने की जरूरत है चलो और बंदूक बनाम मक्खन विश्लेषण। स्वाभाविक रूप से मैं दो आरएमडी दस्तावेज तैयार करता हूं और इसके साथ किया जाता हूं।

अब मान लीजिए कि बॉस साथ आता है और फ्लू आउटब्रेक्स बनाम मक्खन की कीमतों (9 मिमी बारूद के लिए नियंत्रित) की विविधताओं को देखना चाहता है।

  • कोड को कॉपी करके चिपकाने नई रिपोर्ट में रिपोर्ट का विश्लेषण करने के आदि कोड पुनः उपयोग के लिए एक बुरा विचार,
  • मैं इसे अच्छे लग रहे करना चाहते हैं।

    • Flu.Rmd
      • flu_data_import.R
    • Guns_N_Butter.Rmd
      • guns_data_import.R
      • :

      मेरे समाधान के लिए इन फ़ाइलों में परियोजना कारक था

    • butter_data_import.R
प्रत्येक RMD फ़ाइल मैं की तरह कुछ होगा भीतर

:

```{r include=FALSE} 
source('flu_data_import.R') 
``` 

समस्या यहाँ है कि हम reproducibility खो देते हैं। इसका मेरा समाधान प्रत्येक आरएमडी फ़ाइल में शामिल करने के लिए एक सामान्य बाल दस्तावेज़ बनाना है। निश्चित रूप से

```{r autodoc, child='autodoc.Rmd', eval=TRUE} 
``` 

और,, autodoc.Rmd:: तो हर RMD फ़ाइल मैं बनाने के अंत में, मैं इस जोड़ने

Source Data & Code 
---------------------------- 
<div id="accordion-start"></div> 

```{r sourcedata, echo=FALSE, results='asis', warnings=FALSE} 

if(!exists(autodoc.skip.df)) { 
    autodoc.skip.df <- list() 
} 

#Generate the following table: 
for (i in ls(.GlobalEnv)) { 
    if(!i %in% autodoc.skip.df) { 
    itm <- tryCatch(get(i), error=function(e) NA) 
    if(typeof(itm)=="list") { 
     if(is.data.frame(itm)) { 
     cat(sprintf("### %s\n", i)) 
     print(xtable(itm), type="html", include.rownames=FALSE, html.table.attributes=sprintf("class='exportable' id='%s'", i)) 
     } 
    } 
    } 
} 
``` 
### Source Code 
```{r allsource, echo=FALSE, results='asis', warning=FALSE, cache=FALSE} 
fns <- unique(c(compact(llply(.data=llply(.data=ls(all.names=TRUE), .fun=function(x) {a<-get(x); c(normalizePath(getSrcDirectory(a)),getSrcFilename(a))}), .fun=function(x) { if(length(x)>0) { x } })), llply(names(sourced), function(x) c(normalizePath(dirname(x)), basename(x))))) 

for (itm in fns) { 
    cat(sprintf("#### %s\n", itm[2])) 
    cat("\n```{r eval=FALSE}\n") 
    cat(paste(tryCatch(readLines(file.path(itm[1], itm[2])), error=function(e) sprintf("Could not read source file named %s", file.path(itm[1], itm[2]))), sep="\n", collapse="\n")) 
    cat("\n```\n") 
} 
``` 
<div id="accordion-stop"></div> 
<script type="text/javascript"> 
```{r jqueryinclude, echo=FALSE, results='asis', warning=FALSE} 
cat(readLines(url("http://code.jquery.com/jquery-1.9.1.min.js")), sep="\n") 
``` 
</script> 
<script type="text/javascript"> 
```{r tablesorterinclude, echo=FALSE, results='asis', warning=FALSE} 
cat(readLines(url("http://tablesorter.com/__jquery.tablesorter.js")), sep="\n") 
``` 
</script> 
<script type="text/javascript"> 
```{r jqueryuiinclude, echo=FALSE, results='asis', warning=FALSE} 
cat(readLines(url("http://code.jquery.com/ui/1.10.2/jquery-ui.min.js")), sep="\n") 
``` 
</script> 
<script type="text/javascript"> 
```{r table2csvinclude, echo=FALSE, results='asis', warning=FALSE} 
cat(readLines(file.path(jspath, "table2csv.js")), sep="\n") 
``` 
</script> 
<script type="text/javascript"> 
    $(document).ready(function() { 
    $('tr').has('th').wrap('<thead></thead>'); 
    $('table').each(function() { $('thead', this).prependTo(this); }); 
    $('table').addClass('tablesorter');$('table').tablesorter();}); 
    //need to put this before the accordion stuff because the panels being hidden makes table2csv return null data 
    $('table.exportable').each(function() {$(this).after('<a download="' + $(this).attr('id') + '.csv" href="data:application/csv;charset=utf-8,'+encodeURIComponent($(this).table2CSV({delivery:'value'}))+'">Download '+$(this).attr('id')+'</a>')}); 
    $('#accordion-start').nextUntil('#accordion-stop').wrapAll("<div id='accordion'></div>"); 
    $('#accordion > h3').each(function() { $(this).nextUntil('h3').wrapAll("<div>"); }); 
    $('#accordion').accordion({ heightStyle: "content", collapsible: true, active: false }); 
</script> 

एनबी, इस आरएमडी के लिए डिज़ाइन किया गया है -> एचटीएमएल कार्यप्रवाह । यदि आप लेटेक्स या किसी और चीज के साथ जाते हैं तो यह एक बदसूरत गड़बड़ होगी। यह आरएमडी दस्तावेज सभी स्रोत() 'ed फ़ाइलों के लिए वैश्विक वातावरण को देखता है और आपके दस्तावेज़ के अंत में उनके स्रोत को शामिल करता है। इसमें jquery ui, टेबललेटर शामिल है, और दस्तावेज़ को सोर्स की गई फ़ाइलों को दिखाने/छिपाने के लिए एक accordion शैली का उपयोग करने के लिए सेट करता है। यह एक काम प्रगति पर है, लेकिन इसे अपने स्वयं के उपयोगों में अनुकूलित करने के लिए स्वतंत्र महसूस करें।

एक लाइनर नहीं, मुझे पता है। उम्मीद है कि यह आपको कम से कम कुछ विचार देता है :)

1

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

```{R Chunkname, Chunkoptions} 
source(file.R) 
``` 

इस तरह से आप शायद .R फाइलों का एक समूह बना देंगे छोड़ दिया है और आप सभी कोड प्रसंस्करण का लाभ खोना "हिस्सा खंड के बाद "ctrl + alt + n (या + c का उपयोग करके, लेकिन आमतौर पर यह काम नहीं करता है)। लेकिन, मैंने श्री गंड्रुड द्वारा पुनरुत्पादित शोध के बारे में पुस्तक पढ़ी और महसूस किया कि वह निश्चित रूप से बुनाई का उपयोग करता है और।एचटीएमएल फाइलें बनाने के लिए पूरी तरह से आरएमडी फाइलें। मुख्य विश्लेषण स्वयं एक है। फ़ाइल। मुझे लगता है कि यदि आप अपना पूरा विश्लेषण अंदर करना शुरू करते हैं तो आरएमडी दस्तावेज तेजी से बढ़ते हैं।

0

मैं मुख्य विश्लेषण और गणना कोड को रखने की अनुशंसा करता हूं। फ़ाइल और आरएमडी फ़ाइल में आवश्यक भागों को आयात करना। मैंने प्रक्रिया here समझाई है।

1

निम्नलिखित हैक मेरे लिए ठीक काम किया:

library(readr) 
library(stringr) 
source_rmd <- function(file_path) { 
    stopifnot(is.character(file_path) && length(file_path) == 1) 
    .tmpfile <- tempfile(fileext = ".R") 
    .con <- file(.tmpfile) 
    on.exit(close(.con)) 
    full_rmd <- read_file(file_path) 
    codes <- str_match_all(string = full_rmd, pattern = "```(?s)\\{r[^{}]*\\}\\s*\\n(.*?)```") 
    stopifnot(length(codes) == 1 && ncol(codes[[1]]) == 2) 
    codes <- paste(codes[[1]][, 2], collapse = "\n") 
    writeLines(codes, .con) 
    flush(.con) 
    cat(sprintf("R code extracted to tempfile: %s\nSourcing tempfile...", .tmpfile)) 
    source(.tmpfile) 
}