Często mam główny plik R Markdown lub knitr LaTeX, gdzie mam source
inny plik R (np. Do przetwarzania danych). Pomyślałem jednak, że w niektórych przypadkach korzystne byłoby, gdyby te pliki źródłowe były ich własnymi, odtwarzalnymi dokumentami (np. Plik R Markdown, który nie tylko zawiera polecenia dotyczące przetwarzania danych, ale także tworzy odtwarzalny dokument wyjaśniający decyzje dotyczące przetwarzania danych ).
Dlatego chciałbym mieć polecenie takie jak source('myfile.rmd')
w moim głównym pliku R Markdown. że ekstrakt i źródło cały kod R wewnątrz fragmentów kodu r o myfile.rmd
. Oczywiście powoduje to błąd.
Działa to polecenie:
```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```
gdzie results='hide'
można pominąć, jeśli dane wyjściowe były pożądane. To znaczy knitr wyprowadza kod R z myfile.rmd
do myfile.R
.
Jednak nie wydaje się to idealne:
- Powoduje to utworzenie dodatkowego pliku
- musi pojawić się we własnym fragmencie kodu, jeśli wymagana jest kontrola nad wyświetlaczem.
- To nie jest tak eleganckie, jak proste
source(...)
.
Dlatego moje pytanie: czy istnieje bardziej elegancki sposób pozyskiwania kodu R pliku R Markdown?
Rmd
pliku. Ale chcesz również źródłować w innychmarkdown
plikach do pliku, który jest łączony?include
lateksu. Jeśli przecena obsługuje włączanie innych dokumentów przecenowych, utworzenie takiej funkcji powinno być stosunkowo łatwe.Odpowiedzi:
Wygląda na to, że szukasz jednej linijki. Co powiesz na umieszczenie tego w swoim
.Rprofile
?ksource <- function(x, ...) { library(knitr) source(purl(x, output = tempfile()), ...) }
Jednak nie rozumiem, dlaczego chcesz
source()
kod w samym pliku Rmd. Chodzi mi o to,knit()
że uruchomi cały kod w tym dokumencie, a jeśli wyodrębnisz kod i uruchomisz go w kawałku, cały kod zostanie uruchomiony dwukrotnie, gdy będzieszknit()
ten dokument (uruchomisz się w sobie). Te dwa zadania powinny być oddzielne.Jeśli naprawdę chcesz, aby uruchomić cały kod, RStudio uczynił to dość proste:
Ctrl + Shift + R
. Zasadniczo dzwonipurl()
isource()
za sceną.źródło
source()
lubknitr::knit()
uruchomienia kodu. Wiem, że ludzie są mniej zaznajomieni z tym drugim, alepurl()
nie można na nim polegać. Zostałeś ostrzeżony: github.com/yihui/knitr/pull/812#issuecomment-53088636caret
wymagany jest jeden przypadekkernlab
.Uwzględnij wspólny kod w osobnym pliku R, a następnie umieść ten plik R w każdym pliku Rmd, w którym chcesz go umieścić.
na przykład, powiedzmy, że muszę sporządzić dwa raporty: Epidemie grypy i Pistolety kontra Analiza masła. Oczywiście stworzyłbym dwa dokumenty Rmd i skończyłbym z tym.
Teraz przypuśćmy, że szef przyjdzie i chce zobaczyć różnice między epidemiami grypy a cenami masła (kontrolując amunicję 9mm).
Moim rozwiązaniem było uwzględnienie projektu w tych plikach:
w każdym pliku Rmd miałbym coś takiego:
Problem w tym, że tracimy powtarzalność. Moim rozwiązaniem jest utworzenie wspólnego dokumentu podrzędnego do dołączenia do każdego pliku Rmd. Więc na końcu każdego pliku Rmd, który tworzę, dodaję to:
I oczywiście 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>
Uwaga, jest to przeznaczone dla przepływu pracy Rmd -> html. Będzie to brzydki bałagan, jeśli wybierzesz lateks lub cokolwiek innego. Ten dokument Rmd przeszukuje globalne środowisko dla wszystkich plików ed source () i dołącza ich źródło na końcu dokumentu. Zawiera interfejs jquery, tableorter i ustawia dokument tak, aby używał stylu akordeonu do pokazywania / ukrywania plików źródłowych. Jest to praca w toku, ale możesz ją dostosować do własnych potrzeb.
Wiem, że nie jest to jedna kreska. Mam nadzieję, że podsunie Ci przynajmniej kilka pomysłów :)
źródło
Chyba trzeba zacząć myśleć inaczej. Mój problem jest następujący: Napisz każdy kod, który normalnie miałbyś w porcji .Rmd w pliku .R. A dla dokumentu Rmd, którego używasz do robienia na drutach, tj. HTML, zostało tylko
W ten sposób prawdopodobnie utworzysz kilka plików .R i stracisz przewagę przetwarzania całego kodu „kawałek po kawałku” za pomocą ctrl + alt + n (lub + c, ale normalnie to nie działa). Ale przeczytałem książkę o powtarzalnych badaniach pana Gandruda i zdałem sobie sprawę, że zdecydowanie używa on plików knitr i .Rmd wyłącznie do tworzenia plików html. Sama analiza główna to plik .R. Myślę, że dokumenty .Rmd szybko stają się zbyt duże, jeśli zaczniesz robić całą analizę w środku.
źródło
Jeśli jesteś tuż po kodzie, myślę, że coś w tym stylu powinno działać:
readLines
grep
do znajdowania fragmentów kodu, wyszukując wiersze zaczynające się<<<
na przykład odwriteLines
Opakowanie tego w funkcję powinno dać ci to, czego potrzebujesz.
źródło
knit('myfile.rmd', tangle=TRUE)
robi w dzianinie. Myślę, że szukam jednej wkładki, która jednocześnie plącze się i tworzy źródła, a idealnie nie tworzy plików.textConnection
do naśladowania pliku i źródła z niego. Pozwoliłoby to uniknąć tworzenia pliku.textConnection
może być odpowiednim miejscem.Poniższy hack zadziałał dla mnie dobrze:
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) }
źródło
Używam następującej funkcji niestandardowej
source_rmd <- function(rmd_file){ knitr::knit(rmd_file, output = tempfile()) } source_rmd("munge_script.Rmd")
źródło
Wypróbuj funkcję bełkot z knitr:
source(knitr::purl("myfile.rmd", quiet=TRUE))
źródło
Zalecałbym przechowywanie głównego kodu analizy i obliczeń w pliku .R oraz importowanie potrzebnych fragmentów do pliku .Rmd. Tutaj wyjaśniłem ten proces .
źródło
sys.source ("./ your_script_file_name.R", envir = knitr :: knit_global ())
umieść to polecenie przed wywołaniem funkcji zawartych w your_script_file_name.R.
dodanie „./” przed twoją_skryptową_nazwa_pliku.R, aby pokazać kierunek do twojego pliku, jeśli już utworzyłeś projekt.
Możesz zobaczyć ten link, aby uzyskać więcej szczegółów: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html
źródło
to działało dla mnie
source("myfile.r", echo = TRUE, keep.source = TRUE)
źródło
Używam tej jednej linijki:
Zobacz: Mój plik .Rmd staje się bardzo długi. Czy to możliwe, podziel go i source () to mniejsze porcje z głównego .Rmd?
źródło