Подтвердить что ты не робот

Использование циклов с knitr для создания нескольких отчетов в формате PDF... нужно немного помочь, чтобы получить меня за горб

Прежде всего, я должен признать, что я очень новичок в knitr и концепции воспроизводимого анализа, но я вижу его потенциал в улучшении моего текущего рабочего процесса (который включает много копий вставки в word docs).

Мне часто приходится создавать несколько отчетов по группам (больница в этом примере), и в каждой больнице может быть много разных палат, о которых я сообщаю о результатах. Раньше я запускал все мои сюжеты и анализ в R, используя циклы, после чего началась копирование/вставка; однако после прочтения этого сообщения (Can 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. Заранее благодарим за любую помощь, которую вы можете предложить!

4b9b3361

Ответ 1

Вам не нужно переопределять данные в файле .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'))
}

Ответ 2

Отличный вопрос! Это работает для меня с другими битами, которые вы поставили в своем вопросе. Обратите внимание, что я заменил ваш 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}

В результате получается два файла tex (report_A.tex, report_B.tex), четыре файла PDF для цифр (A1, A2, B1, B2) и два PDF файла для отчетов (report_A.pdf, report_B.pdf), каждый с их цифрами в них. Это то, что вы были после?

Ответ 3

В этом ответе я собираюсь ответить на более общий вопрос: "Использование циклов для создания нескольких отчетов в формате PDF", а не ваш конкретный пример. Это связано с тем, что этой тенденции было довольно сложно следовать как нуб. Мне удалось получить его работоспособным (html-версия), так что это мое скромное решение. Вероятно, некоторые из них опубликованы здесь, но я пока не могу их полностью понять.

  • создайте файл RMD с вашим дизайном и сохраните его в рабочем\вводе (в Rstudio: file- > newfile- > R markdown). Этот файл должен включите все функции, необходимые для составления графиков в отчете (просто объявите их в одном из этих фрагментов кода). Подумайте об этом файле как шаблоне для всех будущих отчетов. Не волнуйся о передаче данных в эту среду после того, опишите это в (2). ключевым вопросом для понимания является то, что все вычисления далее по трубопроводу (на данный момент вы отдаете RMD файл).

  • создайте цикл, который вам нужно использовать в файле diffrent control r. В моем случае есть цикл, который   выполняет итерацию по всем файлам в каталоге и получает их в данные   Рамка. то я хочу передать эти данные в 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 получает данные, выполняет некоторые вычисления, выставляет их и публикует в новом файле (также функцией рендеринга). Надеюсь, я помог.