Использование циклов с Knitr для создания нескольких отчетов в формате PDF... нужна небольшая помощь, чтобы справиться с трудностями
Прежде всего, я должен признать, что я очень новичок в knitr и концепции воспроизводимого анализа, но я вижу его потенциал в улучшении моего текущего рабочего процесса (который включает в себя много копий-вставок в документы Word).
Мне часто приходится составлять несколько отчетов по группам (в данном примере Больница), и в каждой больнице может быть много разных отделений, по которым я сообщаю о результатах. Ранее я выполнял все свои графики и анализ в R с использованием циклов, затем началась работа по копированию / вставке; однако после прочтения этого поста ( может ли Sweave автоматически создавать много файлов в формате pdf?), и это дало мне надежду, что я действительно смогу пропустить много шагов и сразу перейти от R к отчету через Rnw / knitr.
Однако, попробовав, я вижу, что есть кое-что, что не совсем работает (так как среда R внутри Rnw, похоже, не распознает циклические переменные, которые я пытаюсь передать ей??).
## 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)
После попытки запустить мой блок кода knit() я получаю эту ошибку:
Error in file(con, "w") : invalid 'description' argument
И когда я просматриваю каталог, в котором должен был быть создан файл *.tex, я вижу, что были созданы 2 pdf-графика из больницы A (ни одного для B), и нет конкретного *.tex-файла для больницы, который можно было бы связать в pdf. Заранее спасибо за любую помощь, которую вы можете предложить!
3 ответа
Вам не нужно переопределять данные в .Rnw
файл, и я думаю, что предупреждение исходит из того факта, что вы кладете выходное имя вместе с Hospital
(полный вектор больниц), а не hosp
(индекс цикла).
Следуя вашему примеру, testingloops.Rnw
было бы
\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}
и файл драйвера R будет просто
## 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'))
}
Отличный вопрос! Это работает для меня с другими битами, которые вы указали в своем вопросе. Обратите внимание, что я заменил ваш hosp
просто x
, Я позвонил вашему Rnw
файл 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))
Я заменил ваши петли сlapply
и анонимные функции, которые часто кажутся более R
-ish.
Здесь вы можете увидеть, где я заменил hosp
с x
в 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}
Результатом являются два текстовых файла (report_A.tex, report_B.tex), четыре PDF-файла для рисунков (A1, A2, B1, B2) и два PDF-файла для отчетов (report_A.pdf, report_B.pdf), каждый из которых содержит свои рисунки. в них. Это то, что вы были после?
В этом ответе я намереваюсь ответить на более общий вопрос: "Использование циклов для создания нескольких отчетов в формате PDF", а не на конкретном примере. Это потому, что этой тенденции было довольно трудно следовать как нуб. Мне удалось заставить его работать в конечном итоге (HTML-версия), так что это мое скромное решение. Здесь, вероятно, есть несколько лучших, но я пока не могу их полностью понять.
создайте файл RMD с вашим дизайном и сохраните его в рабочем каталоге \input (в Rstudio: file->newfile->R markdown). Этот файл должен включать все функции, необходимые для создания графиков в отчете (просто объявите их в одном из этих фрагментов кода). Думайте об этом файле как о шаблоне для всех будущих отчетов. Не беспокойтесь о передаче данных в их среду после того, как их разжевали раньше - я расскажу об этом в (2). Ключевой вопрос, который нужно понять, заключается в том, что все вычисления выполняются далее по конвейеру (в тот момент, когда вы отображаете файл RMD).
создайте цикл, который вам нужно использовать в файле управления diffrent. В моем случае есть цикл, который перебирает все файлы в каталоге и помещает их во фрейм данных. затем я хочу передать эти кадры данных в RMD вместе с другими переменными данных, чтобы построить их. Вот как это делается:
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))} }
Наиболее важной командой является вызов функции render. Это позволяет вам добавлять в среду RMD любые параметры, которые вы пожелаете. Это также позволяет изменить имя отчета и изменить местоположение вывода. Кроме того, вызывая его, вы также генерируете отчет, поэтому вы получаете все это в одной строке (обратите внимание, что если вызов RMD находится внутри функции, вы можете обнаружить, что введенные вами переменные отсутствуют, но отчет будет все равно будет опубликовано правильно)
резюме
Вам нужны два файла - файл RMD, который будет шаблоном для всех дополнительных отчетов и контрольным файлом. контрольный файл получает данные, проверяет их и передает разжеванные параметры в RMD (через функцию рендеринга). RMD получает данные, выполняет некоторые вычисления, строит их и публикует в новом файле (также с помощью функции рендеринга). Я надеюсь, что помог.