2013-03-13 15 views
31

Po pierwsze, muszę przyznać, że jestem bardzo nowy w dzianinie i koncepcji odtwarzalnej analizy, ale mogę widzę jego potencjał w ulepszaniu mojego obecnego przepływu pracy (który obejmuje wiele wklejania wklejenia do dokumentów Worda).Używanie pętli z knitr do generowania wielu raportów w formacie pdf ... potrzebuję małej pomocy, aby mnie pokonać przez garb

Często muszę tworzyć wiele raportów według grupy (szpital w tym przykładzie) iw każdym szpitalu może istnieć wiele różnych obwodów, na których raportuję wynik. Poprzednio uruchomiłem wszystkie moje wykresy i analizy w R używając pętli, a następnie rozpoczęto kopiowanie/wklejanie; jednak po przeczytaniu tego posta (Can Sweave produce many pdfs automatically?) i dało mi to nadzieję, że faktycznie mogę pominąć wiele kroków i przejść od R do raportu przez Rnw/knitr.

Jednak po wypróbowaniu widzę, że jest coś, co nie jest do końca wyćwiczone (ponieważ środowisko R w obrębie Rnw nie wydaje się rozpoznawać zmiennych pętli, które próbuję przekazać do niego ??).

## make my data 
Hospital <- c(rep("A", 20), rep("B", 20)) 
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2) 
Month <- rep(seq(1:10), 4) 
Outcomes <- rnorm(40, 20, 5) 
df <- data.frame(Hospital, Ward, Month, Outcomes) 


## Here is my current work flow-- produce all plots, but export as png and cut/paste 
for(hosp in unique(df$Hospital)){ 
    subgroup <- df[ df$Hospital == hosp,] 
    for(ward in unique(subgroup$Ward)){ 
    subgroup2 <- subgroup[subgroup$Ward == ward,] 
    savename <- paste(hosp, ward) 
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename)) 
    } 
} 
# followed by much copy/pasting 


## Here is what I'm trying to go for using knitr 
library(knitr) 
for (hosp in unique(df$Hospital)){ 
    knit("C:file.path\\testing_loops.Rnw", output=paste('report_', Hospital, '.tex', sep="")) 
} 

## With the following *Rnw file 
## start *.Rnw Code 
\documentclass[10pt]{article} 
\usepackage[margin=1.15 in]{geometry} 
<<loaddata, echo=FALSE, message=FALSE>>= 
    Hospital <- c(rep("A", 20), rep("B", 20)) 
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2) 
Month <- rep(seq(1:10), 4) 
Outcomes <- rnorm(40, 20, 5) 
df <- data.frame(Hospital, Ward, Month, Outcomes) 
subgroup <- df[ df$Hospital == hosp,] 
@ 

\begin{document} 
<<setup, echo=FALSE >>= 
    opts_chunk$set(fig.path = paste("test", hosp , sep="")) 
@ 

Some infomative text about hospital \Sexpr{hosp} 

<<plots, echo=FALSE >>= 
    for(ward in unique(subgroup$Ward)){ 
    subgroup2 <- subgroup[subgroup$Ward == ward,] 
    #  subgroup2 <- subgroup2[ order(subgroup2$Month),] 
    savename <- paste(hosp, ward) 
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename)) 
    } 
@ 
\end{document} 


## To be then turned into pdf with this 
tools::texi2pdf("C:file.path\\report_A.tex", clean = TRUE, quiet = TRUE) 

Po próbuje uruchomić mój dzianiny() kod klocek otrzymuję ten błąd:

Error in file(con, "w") : invalid 'description' argument 

A kiedy patrzę w katalogu, w którym plik * .tex miał być stworzony, widzę wygenerowano 2 działki pdf ze szpitala A (brak dla B) i brak specyficznego dla szpitala pliku * .tex, który można by wykorzystać w pliku pdf. Z góry dziękujemy za każdą pomoc, którą możesz zaoferować!

Odpowiedz

15

Nie trzeba na nowo zdefiniować dane w pliku .Rnw i myślę, że ostrzeżenie jest pochodzących z faktu, że jesteś wprowadzenie nazwy wyjścia razem z Hospital (pełny wektor szpitalach) zamiast hosp (indeks pętli).

Po swoim przykładzie, testingloops.Rnw byłoby

\documentclass[10pt]{article} 
\usepackage[margin=1.15 in]{geometry} 
<<loaddata, echo=FALSE, message=FALSE>>= 
subgroup <- df[ df$Hospital == hosp,] 
@ 

\begin{document} 
<<setup, echo=FALSE >>= 
    opts_chunk$set(fig.path = paste("test", hosp , sep="")) 
@ 

Some infomative text about hospital \Sexpr{hosp} 

<<plots, echo=FALSE >>= 
    for(ward in unique(subgroup$Ward)){ 
    subgroup2 <- subgroup[subgroup$Ward == ward,] 
    #  subgroup2 <- subgroup2[ order(subgroup2$Month),] 
    savename <- paste(hosp, ward) 
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename)) 
    } 
@ 
\end{document} 

i plik sterownika R byłoby tylko

## make my data 
Hospital <- c(rep("A", 20), rep("B", 20)) 
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2) 
Month <- rep(seq(1:10), 4) 
Outcomes <- rnorm(40, 20, 5) 
df <- data.frame(Hospital, Ward, Month, Outcomes) 

## knitr loop 
library("knitr") 
for (hosp in unique(df$Hospital)){ 
    knit2pdf("testingloops.Rnw", output=paste0('report_', hosp, '.tex')) 
} 
+1

+1 dla 'knit2pdf' który zapisuje kilka linii – Ben

+0

Brian, I moja maszyna (z jakiegoś powodu) lubi knit2pdf o wiele więcej niż lapply tools :: texi2pdf! Niesamowite! – Chris

+0

@ Brian Diggs, nie jestem pewien, czy nadal monitorujesz to, ale jeśli chciałem wstawić tekst opisowy * po * działkach każdego oddziału - tak w pętli kodu kreśląc w pliku .Rnw - co byś wiedział Najlepszym sposobem? Próbowałem wstawić kota ("To jest pouczający tekst o \\ Sexpr {ward})" zaraz po spisku. Włączyłem także opcje fragmentów kodu tidy.opts = list (comment = ""), ale knit2pdf umieszcza tekst po obu działkach - nie pod każdym działaniem w pętli, jak zamierzałem. Również podczas kompilacji "\" powoduje błąd ucieczki (?). – Chris

10

Świetne pytanie! Działa to dla mnie z innymi bitami, które podałeś w swoim pytaniu. Zauważ, że zastąpiłem Twój hosp tylko x. Zadzwoniłem plik Rnwtest.rnw

# input data 
Hospital <- c(rep("A", 20), rep("B", 20)) 
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2) 
Month <- rep(seq(1:10), 4) 
Outcomes <- rnorm(40, 20, 5) 
df <- data.frame(Hospital, Ward, Month, Outcomes) 

# generate the tex files, one for each hospital in df 
library(knitr) 
lapply(unique(df$Hospital), function(x) 
     knit("C:\\emacs\\test.rnw", 
      output=paste('report_', x, '.tex', sep=""))) 

# generate PDFs from the tex files, one for each hospital in df 
lapply(unique(df$Hospital), function(x) 
     tools::texi2pdf(paste0("C:\\emacs\\", paste0('report_', x, '.tex')), 
         clean = TRUE, quiet = TRUE)) 

mam wymienić swoje pętle z lapply i anonimowych funkcji, które często wydają się być traktowane bardziej R -ish.

Tutaj można zobaczyć, gdzie zastąpił hosp z x w pliku rnw:

\documentclass[10pt]{article} 
\usepackage[margin=1.15 in]{geometry} 
<<loaddata, echo=FALSE, message=FALSE>>= 
    Hospital <- c(rep("A", 20), rep("B", 20)) 
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2) 
Month <- rep(seq(1:10), 4) 
Outcomes <- rnorm(40, 20, 5) 
df <- data.frame(Hospital, Ward, Month, Outcomes) 
subgroup <- df[ df$Hospital == x,] 
@ 

\begin{document} 
<<setup, echo=FALSE >>= 
    opts_chunk$set(fig.path = paste("test", x , sep="")) 
@ 

Some informative text about hospital \Sexpr{x} 

<<plots, echo=FALSE >>= 
    for(ward in unique(subgroup$Ward)){ 
    subgroup2 <- subgroup[subgroup$Ward == ward,] 
    #  subgroup2 <- subgroup2[ order(subgroup2$Month),] 
    savename <- paste(x, ward) 
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename)) 
    } 
@ 
\end{document} 

Rezultatem jest dwa pliki tex (report_A.tex, report_B.tex), cztery PDF do figur (A1 , A2, B1, B2) i dwa pliki PDF dla raportów (report_A.pdf, report_B.pdf), z których każda zawiera ich liczby. Czy tego właśnie szukasz?

+2

Absolutnie! Mam kłopot (teraz) uzyskując drugi lapply chunk, aby zachowywał się tak, jak przechodzi przez narzędzia: texi2pdf, ale sam mogę to sobie wyobrazić. Właśnie pierwsze lapply knit moje pliki * .tex jest fantastyczne! Wielkie dzięki!! – Chris

+1

Cieszę się, że pomógł, czy próbowałeś 'knit2pdf' jak w odpowiedzi Briana Diggsa? Możesz zastąpić drugą bibliotekę 'lapply' with:' (knitr); lapply (unikalny (df $ Hospital), function (x) knit2pdf ("C: \\ emacs \\ test.rnw", output = paste0 ('report_', x, '.tex'))) ' – Ben

+0

Przez 'replace "Mam na myśli" pozbądź się "drugiego" lapply ", wybacz mi. – Ben

0

W tej odpowiedzi Zamierzam odpowiedzieć na bardziej ogólne pytanie: „Korzystanie pętle produkować wiele raportów pdf ", a nie twój konkretny przykład. To dlatego, że ten trend był dość trudny do naśladowania jako noob. Udało mi się go ostatecznie uruchomić (wersja html), więc to moje skromne rozwiązanie. Prawdopodobnie opublikowano tu kilka lepszych, ale nie mogę jeszcze w pełni ich zrozumieć.

  1. utworzyć plik RMD z projektu i zapisać go w katalogu roboczego \ input (w Rstudio: Plik-> newfile-> R Przecena). Ten plik powinien zawierać zawiera wszystkie funkcje niezbędne do utworzenia wykresów w raporcie (wystarczy zadeklarować je w jednym z tych fragmentów kodu). Wyobraź sobie ten plik jako szablon dla wszystkich przyszłych raportów. Nie martw się o przekazaniu danych do środowiska po uprzednim przeżuciu - będę je zawierał pod numerem (2). kluczową kwestią do zrozumienia jest to, że wszystkie obliczenia są wykonywane w dalszej części potoku (w momencie renderowania pliku RMD ).

  2. utwórz pętlę, której należy użyć w innym pliku kontrolnym r. W moim przypadku istnieje pętla, która iteruje nad wszystkimi plikami w katalogu i przenosi je do ramki danych . następnie chcę przekazać te ramki danych do RMD wraz z innymi zmiennymi danych, aby je wykreślić. Jest to, jak jej zrobić:

    run_on_all<-function(path_in="path:\\where\\your\\input\\and\\RMD\\is", path_out="path:\\where\\your\\output\\will\\be") setwd(path_in) ibrary(rmarkdown) library(knitr) list_of_file_names=list.files(path = getwd, pattern = "*.csv") #this gets a list of the input files names for (file_name in list_of_file_names) { data=read.csv(file_name) #read file into data frame report_name=paste(some_variable_name,".html",sep="") render("your_template.Rmd",output_file =report_name,output_dir =path_out,list(data,all other parameters you want to input into the RMD))} }

  3. Najważniejsza komenda jest funkcja połączenia renderowanie. To pozwala na wrzucenie do środowiska RMD dowolnych paramentów, które chcesz. Umożliwia także zmianę nazwy raportu i zmianę lokalizacji wyjściowej. Dodatkowo, wywołując go, generujesz także raport w postaci , dzięki czemu otrzymujesz go wszystkie w jednym wierszu (pamiętaj, że jeśli wywołanie RMD znajduje się w funkcji, może się okazać, że zmienne, które wprowadzasz, są niedostępne, ale raport nadal będą publikowane poprawnie)

podsumowanie

istnieją dwa pliki, które potrzebujesz-file RMD, że będzie szablon dla wszystkich dodatkowych raportów i pliku kontrolnego. plik kontrolny pobiera dane, przeżuwa je i przekazuje przeładowane parametry do RMD (za pomocą funkcji renderowania). RMD pobiera dane, wykonuje niektóre obliczenia, kreśli je i publikuje w nowym pliku (również za pomocą funkcji renderowania). Mam nadzieję, że pomogłem.

Powiązane problemy