Używanie pętli z knitr do tworzenia wielu raportów pdf ...

Po pierwsze, muszę przyznać, że jestem bardzo nowy w knitr i koncepcji powtarzalnej analizy, ale widzę jej potencjał w poprawie mojego obecnego przepływu pracy (który obejmuje wiele kopiowania-wklejania do dokumentów word).

Często muszę tworzyć wiele raportów według grup (w tym przykładzie szpital) i w każdym szpitalu może być wiele różnych oddziałów, na których raportuję wynik. Wcześniej uruchomiłem wszystkie moje wykresy i analizy w R za pomocą pętli, a następnie kopiowanie / wklejanie pracy rozpoczęty; jednak po przeczytaniu tego postu (czy Sweave może produkować wiele plików PDF automatycznie?) i dało mi to nadzieję, że będę w stanie pominąć wiele kroków i przejść od R do raportu przez RNW / knitr.

Jednak po wypróbowaniu widzę, że jest coś, co nie do końca działa (ponieważ środowisko R w Rnw nie wydaje się rozpoznawać zmiennych zapętlających, 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óbie uruchomienia kodu dzianiny () chunk I get this error:

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

I kiedy zajrzę do katalogu, w którym *.plik tex miał być utworzony, widzę, że powstały 2 działki pdf ze szpitala A (brak Dla B) i brak specyficznych dla szpitala *.plik tex do pobrania w formacie pdf. Z góry dziękuję za wszelką pomoc!

 31
Author: Community, 2013-03-14

3 answers

Nie musisz ponownie definiować danych w pliku .Rnw i myślę, że Ostrzeżenie pochodzi z faktu, że umieszczasz nazwę wyjścia razem z Hospital (pełny wektor szpitali), a nie hosp (indeks pętli).

Idąc za twoim przykładem, {[5] } będzie

\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 driver R byłby po prostu

##  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'))
}
 15
Author: Brian Diggs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 22:34:59

Świetne pytanie! To działa dla mnie z innymi kawałkami, które dostarczyłeś w swoim pytaniu. Zauważ, że zamieniłem Twoje {[2] } na x. I ' ve called your Rnw file test.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))

Zastąpiłem Twoje pętle lapply i funkcjami anonimowymi, które często wydają się być uważane za bardziej R-owskie.

Tutaj możesz zobaczyć gdzie zamieniłem hosp na 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}

Wynikiem są dwa pliki tex (report_A. tex, report_B.tex), cztery pliki PDF do dane liczbowe (A1, A2, B1, B2) oraz dwa pliki PDF do raportów (report_A.pdf, report_B. pdf), z których każdy zawiera swoje dane liczbowe. O to ci chodziło?

 10
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-13 22:31:32

W tej odpowiedzi zamierzam odpowiedzieć na bardziej ogólne Pytanie: "Używanie pętli do tworzenia wielu raportów pdf" , a nie konkretny przykład. To dlatego, że trend ten był dość trudny do naśladowania jako noob. Udało mi się to ostatecznie uruchomić (wersja html) , więc jest to moje skromne rozwiązanie. Są chyba jakieś lepsze opublikowane tutaj, po prostu nie mogę ich jeszcze w pełni zrozumieć.

  1. Utwórz plik RMD ze swoim projektem i zapisz go w working \ input katalog (w Rstudio: file - > newfile-> r markdown). Ten plik powinien dołącz wszystkie funkcje potrzebne do tworzenia wykresów w raporcie(po prostu zadeklaruj je w jednym z tych fragmentów kodu). Potraktuj ten plik jako szablon dla wszystkich przyszłych raportów. Nie martw się. o przekazaniu danych do jego środowiska po wcześniejszym pogryzieniu-będę cover that in (2). kluczową kwestią do zrozumienia jest to, że wszystkie obliczenia są wykonane dalej w dół rurociągu (w momencie renderowania RMD plik).

  2. Utwórz pętlę musisz użyć w innym pliku kontrolnym R. W moim przypadku istnieje pętla, która iteruje wszystkie pliki w katalogu i pobiera je do danych rama. następnie chcę przekazać te ramki danych do RMD, wraz z inne zmienne danych, w celu ich wykreślenia. Tak to się robi:

    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żniejszą komendą jest wywołanie funkcji render. Informatyka pozwala na wrzucanie do środowiska RMD dowolnych paramenterów. Pozwala również na zmienić nazwę raportu i zmienić miejsce wyjścia. Ponadto, wywołując go, generujesz również raport, więc masz wszystko w jednej linii.(zauważ, że jeśli wywołanie RMD znajduje się wewnątrz funkcji, może się okazać, że zmiennych, które wprowadzasz, brakuje, ale raport nadal będzie opublikowany poprawnie)

Podsumowanie

Potrzebne są dwa pliki-plik RMD, który będzie szablonem dla wszystkich dodatkowych raportów oraz Plik Kontrolny. Plik Kontrolny otrzymuje dane, żuje je i przekazuje rozgryzone parametry do RMD (poprzez funkcję render). RMD pobiera dane, wykonuje pewne obliczenia, wykreśla je i publikuje w nowym Pliku (również za pomocą funkcji render). Mam nadzieję, że pomogłem.

 0
Author: amann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 08:46:38