J'ai souvent un fichier principal R Markdown ou un fichier Knitr LaTeX où j'ai source
un autre fichier R (par exemple, pour le traitement des données). Cependant, je pensais que dans certains cas, il serait avantageux que ces fichiers source soient leurs propres documents reproductibles (par exemple, un fichier R Markdown qui comprend non seulement des commandes pour le traitement des données, mais produit également un document reproductible qui explique les décisions de traitement des données. ).
Ainsi, j'aimerais avoir une commande comme source('myfile.rmd')
dans mon fichier principal R Markdown. qui extraire et source tout le code R à l'intérieur des morceaux de code R de myfile.rmd
. Bien sûr, cela donne lieu à une erreur.
La commande suivante fonctionne:
```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```
où results='hide'
pourrait être omis si la sortie était souhaitée. Ie, knitr sort le code R de myfile.rmd
dans myfile.R
.
Cependant, cela ne semble pas parfait:
- il en résulte la création d'un fichier supplémentaire
- il doit apparaître dans son propre bloc de code si le contrôle de l'affichage est requis.
- Ce n'est pas aussi élégant que simple
source(...)
.
Ainsi ma question: existe-t-il une manière plus élégante de rechercher le code R d'un fichier R Markdown?
Rmd
fichier. Mais vous souhaitez également générer d'autresmarkdown
fichiers dans un fichier en cours de tricotage?include
en latex. Si le démarque prend en charge l'inclusion d'autres documents de démarque, il devrait être relativement facile de créer une telle fonction.Réponses:
Il semble que vous recherchiez un monoplace. Que diriez-vous de mettre cela dans votre
.Rprofile
?ksource <- function(x, ...) { library(knitr) source(purl(x, output = tempfile()), ...) }
Cependant, je ne comprends pas pourquoi vous voulez
source()
le code dans le fichier Rmd lui-même. Je veux direknit()
, exécutera tout le code de ce document, et si vous extrayez le code et l'exécutez en un morceau, tout le code sera exécuté deux fois lorsque vousknit()
présenterez ce document (vous vous exécutez vous-même). Les deux tâches doivent être séparées.Si vous voulez vraiment exécuter tout le code, rstudio a fait ce assez facile:
Ctrl + Shift + R
. Il appelle essentiellementpurl()
etsource()
derrière la scène.la source
source()
ouknitr::knit()
d'exécuter le code. Je sais que les gens sont moins familiers avec ce dernier, mais cepurl()
n'est pas fiable. Vous avez été prévenu: github.com/yihui/knitr/pull/812#issuecomment-53088636caret
requiskernlab
avec svm.Factorisez le code commun dans un fichier R séparé, puis source ce fichier R dans chaque fichier Rmd dans lequel vous le souhaitez.
Donc, par exemple, disons que j'ai deux rapports à faire, les épidémies de grippe et l'analyse des armes à feu et du beurre. Naturellement, je créerais deux documents Rmd et j'en aurais terminé.
Supposons maintenant que le patron vienne et veuille voir les variations des épidémies de grippe par rapport aux prix du beurre (en contrôlant les munitions de 9 mm).
Ma solution était de factoriser le projet dans ces fichiers:
dans chaque fichier Rmd, j'aurais quelque chose comme:
Le problème ici est que nous perdons la reproductibilité. Ma solution à cela est de créer un document enfant commun à inclure dans chaque fichier Rmd. Donc à la fin de chaque fichier Rmd que je crée, j'ajoute ceci:
Et, bien sûr, 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>
NB, ceci est conçu pour le workflow Rmd -> html. Ce sera un désordre laid si vous optez pour du latex ou autre chose. Ce document Rmd recherche dans l'environnement global tous les fichiers ed source () et inclut leur source à la fin de votre document. Il inclut jquery ui, tablesorter et configure le document pour qu'il utilise un style accordéon pour afficher / masquer les fichiers source. C'est un travail en cours, mais n'hésitez pas à l'adapter à vos propres usages.
Pas un one-liner, je sais. J'espère que cela vous donne au moins des idées :)
la source
On devrait probablement commencer à penser différemment. Mon problème est le suivant: Écrivez chaque code que vous auriez normalement eu dans un bloc .Rmd dans un fichier .R. Et pour le document Rmd que vous utilisez pour tricoter c'est à dire un html, il ne vous reste plus que
De cette façon, vous créerez probablement un tas de fichiers .R et vous perdrez l'avantage de traiter tout le code "morceau après morceau" en utilisant ctrl + alt + n (ou + c, mais normalement cela ne fonctionne pas). Mais, j'ai lu le livre sur la recherche reproductible par M. Gandrud et réalisé, qu'il utilise définitivement les fichiers knitr et .Rmd uniquement pour créer des fichiers html. L'analyse principale elle-même est un fichier .R. Je pense que les documents .Rmd deviennent rapidement trop volumineux si vous commencez à faire toute votre analyse à l'intérieur.
la source
Si vous êtes juste après le code, je pense que quelque chose de ce genre devrait fonctionner:
readLines
grep
pour trouver les morceaux de code, en recherchant les lignes commençant par<<<
exemplewriteLines
Emballer cela dans une fonction devrait vous donner ce dont vous avez besoin.
la source
knit('myfile.rmd', tangle=TRUE)
fait Knitr. Je suppose que je recherche une ligne unique qui à la fois s'emmêle et source et ne crée idéalement aucun fichier.textConnection
pour imiter un fichier et en tirer la source. Cela éviterait la création d'un fichier.textConnection
pourrait être l'endroit où chercher.Le hack suivant a bien fonctionné pour moi:
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) }
la source
J'utilise la fonction personnalisée suivante
source_rmd <- function(rmd_file){ knitr::knit(rmd_file, output = tempfile()) } source_rmd("munge_script.Rmd")
la source
Essayez la fonction purl de knitr:
source(knitr::purl("myfile.rmd", quiet=TRUE))
la source
Je recommanderais de conserver le code d'analyse et de calcul principal dans le fichier .R et d'importer les morceaux au besoin dans le fichier .Rmd. J'ai expliqué le processus ici .
la source
sys.source ("./ votre_nom_fichier_script.R", envir = knitr :: knit_global ())
mettez cette commande avant d'appeler les fonctions contenues dans le fichier your_script_file_name.R.
le "./" ajoutant avant votre_nom_fichier_script.R pour indiquer la direction de votre fichier si vous avez déjà créé un projet.
Vous pouvez voir ce lien pour plus de détails: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html
la source
cela a fonctionné pour moi
source("myfile.r", echo = TRUE, keep.source = TRUE)
la source
J'utilise ce one-liner:
Voir: Mon fichier .Rmd devient très long. Est-ce possible de le diviser et de source () ses portions plus petites du .Rmd principal?
la source