Форматирование вывода с помощью Knitr, ggplot2 и xtable

Я пытаюсь выполнить следующую задачу с помощью Knitr, ggplot2 и xtables:

  • Создайте несколько аннотированных графиков бета-распределений с помощью ggplot2
  • Запишите результат в виде макета, чтобы у меня был график и соответствующая сводная таблица Stats после него для каждого графика.
  • Напишите код так, чтобы отчеты в формате PDF и HTML можно было создавать в презентабельном виде.

Вот моя попытка выполнить эту задачу (файл Rnw):

\documentclass{article}

\begin{document}

Test for ggplot2 with Knitr

<<Initialize, echo=FALSE>>=
library(ggplot2)
library(ggthemes)
library(data.table)
library(grid)
library(xtable)
library (plyr)

pltlist <- list()
statlist <- list()

@

The libraries are loaded. Now run the main loop


<<plotloop, echo=FALSE>>=
    for (k in seq(1,7)){
      x <- data.table(rbeta(100000,1.6,14+k))
      xmean <- mean(x$V1, na.rm=T)
      xqtl <- quantile(x$V1, probs = c(0.995), names=F)
      xdiff <- xqtl - xmean
      dens <- density(x$V1)
      xscale <- (max(dens$x, na.rm=T) - min(dens$x, na.rm=T))/100
      yscale <- (max(dens$y, na.rm=T))/100
      y_max <- max(dens$y, na.rm=T)
      y_intercept <- y_max-(10*yscale)
      data <- data.frame(x)

      y <- ggplot(data, aes(x=V1)) + geom_density(colour="darkgreen", size=2, fill="green",alpha=.3) +
        geom_vline(xintercept = xmean, colour="blue", linetype = "longdash") +
        geom_vline(xintercept = xqtl, colour="red", linetype = "longdash") +
        geom_segment(aes(x=xmean, xend=xqtl, y=y_intercept, yend=y_intercept), colour="red", linetype = "solid", arrow = arrow(length = unit(0.2, "cm"), ends = "both", type = "closed")) +
        annotate("text", x = xmean+xscale, y = y_max, label = paste("Val1:",round(xmean,4)), hjust=0) +
        annotate("text", x = xqtl+xscale, y = y_max, label = paste("Val2:",round(xqtl,4))) +
        annotate("text", x = xmean+10*xscale, y = y_max-15*yscale, label = paste("Val3:",round(xdiff,4))) +
        xlim(min(dens$x, na.rm=T), xqtl + 9*xscale) +
        xlab("Values") +
        ggtitle("Beta Distribution") +
        theme_bw() +
        theme(plot.title = element_text(hjust = 0, vjust=2))

      pltlist[[k]] <- y
      statlist[[k]] <- list(mean=xmean, quantile=xqtl) 

}

stats <- ldply(statlist, data.frame)
@

Plots are ready. Now Plot them

<<PrintPlots, warning=FALSE, results='asis', echo=FALSE, cache=TRUE,  fig.height=3.5>>=
for (k in seq(1,7)){
  print(pltlist[[k]])
  print(xtable(stats[k,], caption="Summary Statistics", digits=6))
}

@

Plotting Finished.


\end{document}

После запуска этого кода я столкнулся с несколькими проблемами.

  1. Когда я запускаю этот код так же, как код R, как только я пытаюсь распечатать графики в списке, горизонтальная линия из части geom_segment начинает перемещаться повсюду. Однако, если я нанесу цифры по отдельности, не помещая их в список, цифры будут хорошими, как я и ожидал.
  2. Только последний график такой, как я ожидал, на всех других графиках линия geom_segment перемещается случайным образом.
  3. Я также не могу поставить отдельную подпись для графиков, как могу для таблиц.

На заметку:

  • Я храню бета-случайные числа в data.table, поскольку в нашем фактическом коде мы используем data.table. Однако в целях тестирования ggplot2 таким способом я конвертирую data.table в data.frame, как того требует ggplot2.
  • Мне также нужно сгенерировать случайные числа в цикле и сгенерировать графики для каждой итерации (так что что-то вроде сначала генерации случайных чисел, а затем использования melt здесь не сработает), поскольку генерация случайных чисел имитирует сложный вызов базы данных на итерацию петля.

Я использую RStudio версии 0.98.1091 и R версии 3.1.2 (2014-10-31) в Windows 8.1

Это ожидаемый сюжет: Ожидаемый сюжет

Это график, который я получаю при построении из списка: График из списка

Мой вывод в формате PDF: Вывод в PDF

Пожалуйста, посоветуйте, есть ли идеи для решения.

Спасибо,

SG


person SGH    schedule 26.12.2014    source источник
comment
1. Похоже, вы используете Sweave для генерации вывода. Я не вижу существенного LaTeX в вашем коде, поэтому пакет Knitr может быть лучше для ваших целей. Knitr может выводить документы PDF и HTML. 2. Ссылки на Ожидаемый участок и Участок из списка не работают.   -  person zhaoy    schedule 26.12.2014
comment
Спасибо за комментарий zhaoy. Я исправил код, чтобы работать с knitr. Не знаю, почему ссылки на рисунки напрямую не работают. Однако если вы щелкните правой кнопкой мыши и откроете изображение в новой вкладке, изображения будут там.   -  person SGH    schedule 27.12.2014


Ответы (2)


Я не знаю, почему горизонтальная линия в geom_segment "перемещается" от участка к графику, а не охватывает xmean на xqtl. Однако мне удалось получить горизонтальную линию в правильном месте, получив значение из кадра данных stats, а не путем прямого вычисления среднего и квантиля. Вам просто нужно создать фрейм данных stats до цикла, а не после, чтобы вы могли использовать его в цикле.

  stats <- ldply(statlist, data.frame)

  for (k in seq(1,7)){
    ...

    y <- ggplot(data, aes(x=V1)) + 
        ...
        geom_segment(aes(x=stats[k,1], xend=stats[k,2], y=y_intercept, yend=y_intercept), 
                 colour="red", linetype = "solid", 
                 arrow = arrow(length = unit(0.2, "cm"), ends = "both", type = "closed")) +
        ...

  pltlist[[k]] <- y
  statlist[[k]] <- list(mean=xmean, quantile=xqtl) 
  }

Надеюсь, кто-нибудь еще сможет объяснить аномальное поведение, но, по крайней мере, это, похоже, решит проблему.

Для заголовка рисунка вы можете добавить аргумент fig.cap к блоку, где вы строите рисунки, хотя это приводит к тому же заголовку для каждого рисунка и заставляет рисунки и таблицы строиться в отдельных группах, а не чередоваться:

<<PrintPlots, warning=FALSE, results='asis', echo=FALSE, cache=TRUE, fig.cap="Caption", fig.height=3.5>>=
for (k in seq(1,7)){
  print(pltlist[[k]])
  print(xtable(stats[k,], caption="Summary Statistics", digits=6))
}
person eipi10    schedule 26.12.2014
comment
Спасибо, что нашли время разобраться с проблемой eipi10 :) Ваше решение работает для проблемы по оси абсцисс. Я попытался исправить это аналогичным образом для оси Y, но безуспешно. geom_segment должен ожидать фрейм данных для координат x и y. Итак, я попробовал что-то вроде этого: geom_segment(aes(x=x_coords[1,1], xend=x_coords[1,2], y=y_coords[1,1], yend=y_coords[1,1])), установив следующие переменные: y_coords <- data.frame(y_max-(10*yscale)) и x_coords <- data.frame(c(xmean, xqtl)), непосредственно перед оператором y <- ggplot( ... внутри цикла. Проблема не устранена. - person SGH; 27.12.2014

Возможно, вы захотите использовать R Markdown и knitr, что проще, чем использование LaTeX и R (как также предлагает zhaoy).

Вы также можете ознакомиться с пакетом ReporteRs. Я думаю, что это на самом деле проще в использовании, чем вязальщица. Однако с его помощью вы не можете создавать PDF-файлы. Но вы можете использовать pandoc для преобразования их в PDF-файлы.

person Caner    schedule 26.12.2014
comment
Я обнаружил, что код OP отлично работает с knitr в RStudio, создавая файл PDF точно так, как ожидалось. Неправильное положение горизонтальной линии не кажется knitr проблемой, поскольку это случается независимо от того, запускаю ли я код в интерактивном режиме или через knitr. - person eipi10; 26.12.2014
comment
Спасибо, Канер. Я попробую пакет ReporteRs. Однако, как говорит eipi, код, похоже, работает с knitr и Rstudio, за исключением горизонтальной линии. Я попробую ReporteRs, как только смогу - person SGH; 27.12.2014