Ich habe oft eine Haupt-R-Markdown-Datei oder eine Knitr-LaTeX-Datei, in der ich source
eine andere R-Datei habe (z. B. für die Datenverarbeitung). Ich dachte jedoch, dass es in einigen Fällen vorteilhaft wäre, wenn diese Quelldateien ihre eigenen reproduzierbaren Dokumente wären (z. B. eine R-Markdown-Datei, die nicht nur Befehle für die Datenverarbeitung enthält, sondern auch ein reproduzierbares Dokument erstellt, das die Datenverarbeitungsentscheidungen erklärt ).
Daher möchte ich einen Befehl wie source('myfile.rmd')
in meiner Haupt-R-Markdown-Datei haben. das würde den gesamten R-Code in den R-Code-Blöcken von extrahieren und beschaffen myfile.rmd
. Dies führt natürlich zu einem Fehler.
Der folgende Befehl funktioniert:
```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```
wo results='hide'
könnte weggelassen werden, wenn die Ausgabe gewünscht wurde. Dh knitr gibt den R-Code von myfile.rmd
in aus myfile.R
.
Es scheint jedoch nicht perfekt zu sein:
- Dies führt zur Erstellung einer zusätzlichen Datei
- Es muss in einem eigenen Codeblock angezeigt werden, wenn die Kontrolle über die Anzeige erforderlich ist.
- Es ist nicht so elegant wie einfach
source(...)
.
Daher meine Frage: Gibt es eine elegantere Möglichkeit, den R-Code einer R-Markdown-Datei zu beschaffen?
Rmd
Datei einbinden. Sie möchten aber auch anderemarkdown
Dateien in eine zu strickende Datei einspeisen?include
Latex. Wenn Markdown die Aufnahme anderer Markdown-Dokumente unterstützt, sollte es relativ einfach sein, eine solche Funktion zu erstellen.Antworten:
Es scheint, dass Sie nach einem Einzeiler suchen. Wie wäre es damit, dies in Ihre zu setzen
.Rprofile
?ksource <- function(x, ...) { library(knitr) source(purl(x, output = tempfile()), ...) }
Ich verstehe jedoch nicht, warum Sie
source()
den Code in der Rmd-Datei selbst wollen. Ich meine,knit()
wird den gesamten Code in diesem Dokument ausführen, und wenn Sie den Code extrahieren und in einem Block ausführen, wird der gesamte Code zweimal ausgeführt, wenn Sieknit()
dieses Dokument verwenden (Sie führen sich selbst in sich selbst aus). Die beiden Aufgaben sollten getrennt sein.Wenn Sie wirklich den gesamten Code ausführen möchten, hat RStudio dies ziemlich einfach gemacht :
Ctrl + Shift + R
. Es ruft im Grundepurl()
undsource()
hinter den Kulissen.quelle
source()
oderknitr::knit()
auszuführen. Ich weiß, dass die Leute mit letzterem weniger vertraut sind, aberpurl()
nicht zuverlässig sind. Sie wurden gewarnt: github.com/yihui/knitr/pull/812#issuecomment-53088636caret
erforderlichkernlab
.Berücksichtigen Sie den allgemeinen Code in einer separaten R-Datei und geben Sie diese R-Datei in jede Rmd-Datei ein, in der Sie sie haben möchten.
Nehmen wir zum Beispiel an, ich muss zwei Berichte erstellen: Grippeausbrüche und Guns vs Butter Analysis. Natürlich würde ich zwei Rmd-Dokumente erstellen und damit fertig sein.
Nehmen wir nun an, der Chef kommt vorbei und möchte die Variationen der Grippeausbrüche im Vergleich zu den Butterpreisen sehen (Kontrolle über 9-mm-Munition).
Meine Lösung bestand darin, das Projekt in folgende Dateien einzubeziehen:
In jeder Rmd-Datei hätte ich so etwas wie:
Das Problem hierbei ist, dass wir die Reproduzierbarkeit verlieren. Meine Lösung besteht darin, ein gemeinsames untergeordnetes Dokument zu erstellen, das in jede Rmd-Datei aufgenommen wird. Am Ende jeder von mir erstellten Rmd-Datei füge ich Folgendes hinzu:
Und natürlich autodoc.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>
Hinweis: Dies ist für den Rmd -> HTML-Workflow vorgesehen. Dies wird ein hässliches Durcheinander sein, wenn Sie mit Latex oder etwas anderem gehen. Dieses Rmd-Dokument durchsucht die globale Umgebung nach allen ed-Dateien (source ()) und enthält deren Quelle am Ende Ihres Dokuments. Es enthält jquery ui, tablesorter und richtet das Dokument so ein, dass es einen Akkordeonstil zum Ein- / Ausblenden von Quelldateien verwendet. Es ist in Arbeit, aber Sie können es jederzeit an Ihre eigenen Zwecke anpassen.
Ich weiß, kein Einzeiler. Hoffe es gibt dir wenigstens ein paar Ideen :)
quelle
Wahrscheinlich sollte man anders denken. Mein Problem ist das folgende: Schreiben Sie jeden Code, den Sie normalerweise in einem .Rmd-Block hatten, in eine .R-Datei. Und für das Rmd-Dokument, das Sie zum Stricken verwenden, z. B. ein HTML, haben Sie nur noch übrig
Auf diese Weise erstellen Sie wahrscheinlich eine Reihe von .R-Dateien und verlieren den Vorteil, den gesamten Code "Block für Block" mit Strg + Alt + N (oder + C, aber normalerweise funktioniert dies nicht) zu verarbeiten. Aber ich habe das Buch über reproduzierbare Forschung von Herrn Gandrud gelesen und festgestellt, dass er definitiv Knitr- und .Rmd-Dateien ausschließlich zum Erstellen von HTML-Dateien verwendet. Die Hauptanalyse selbst ist eine .R-Datei. Ich denke, RMD-Dokumente werden schnell zu groß, wenn Sie Ihre gesamte Analyse im Inneren durchführen.
quelle
Wenn Sie direkt nach dem Code sind, denke ich, dass etwas in dieser Richtung funktionieren sollte:
readLines
grep
die Code - Stücke zu finden, die für die Linien zu suchen , die mit beginnen<<<
zum BeispielwriteLines
Wenn Sie dies in eine Funktion einwickeln, erhalten Sie das, was Sie benötigen.
quelle
knit('myfile.rmd', tangle=TRUE)
Knitr. Ich schätze, ich suche einen Einzeiler, der sowohl Verwicklungen als auch Quellen enthält und im Idealfall keine Dateien erstellt.textConnection
eine Datei imitieren und daraus eine Quelle erstellen. Dies würde verhindern, dass eine Datei erstellt wird.textConnection
könnte der Ort sein, um zu suchen.Der folgende Hack hat bei mir gut funktioniert:
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) }
quelle
Ich benutze die folgende benutzerdefinierte Funktion
source_rmd <- function(rmd_file){ knitr::knit(rmd_file, output = tempfile()) } source_rmd("munge_script.Rmd")
quelle
Probieren Sie die Purl-Funktion von Knitr aus:
source(knitr::purl("myfile.rmd", quiet=TRUE))
quelle
Ich würde empfehlen, den Hauptanalyse- und Berechnungscode in der .R-Datei zu belassen und die Chunks nach Bedarf in die .Rmd-Datei zu importieren. Ich habe den Prozess hier erklärt .
quelle
sys.source ("./ your_script_file_name.R", envir = knitr :: knit_global ())
Setzen Sie diesen Befehl, bevor Sie die Funktionen aufrufen, die in your_script_file_name.R enthalten sind.
das "./", das vor your_script_file_name.R hinzugefügt wird, um die Richtung zu Ihrer Datei anzuzeigen, wenn Sie bereits ein Projekt erstellt haben.
Sie können diesen Link für weitere Details sehen: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html
quelle
das hat bei mir funktioniert
source("myfile.r", echo = TRUE, keep.source = TRUE)
quelle
Ich benutze diesen Einzeiler:
Siehe: Meine .Rmd-Datei wird sehr lang. Ist das möglich, es zu teilen und source () es sind kleinere Teile von main .Rmd?
quelle