【问题标题】:Formatting output with Knitr, ggplot2 and xtable使用 Knitr、ggplot2 和 xtable 格式化输出
【发布时间】:2015-02-23 14:50:21
【问题描述】:

我正在尝试使用 Knitr、ggplot2 和 xtables 完成以下任务:

  • 使用 ggplot2 生成多个带注释的 beta 分布图
  • 在布局中编写输出,以便我有一个图,以及它后面的相应汇总统计表,用于每个图。
  • 编写代码,以便可以以美观的方式生成 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. 我也无法像为表格一样为图表添加单独的标题。

注意事项:

  • 我将 beta 随机数存储在 data.table 中,因为在我们的实际代码中,我们使用的是 data.table。然而,为了以这种方式测试 ggplot2,我将 data.table 转换为 data.frame,因为 ggplot2 需要。
  • 我还需要在循环中生成随机数并在每次迭代时生成图(所以像首先生成随机数然后使用melt 这样的方法在这里不起作用),因为生成随机数是在模拟一个复杂的每次循环迭代都会调用数据库。

我正在使用 RStudio 版本 0.98.1091 和 Windows 8.1 上的 R 版本 3.1.2 (2014-10-31)

这是预期的情节:

这是我从列表中绘制时得到的图:

我的 PDF 格式输出: PDF Output

如果有任何解决方案的想法,请提出建议。

谢谢,

SG

【问题讨论】:

  • 1.您似乎正在使用 Sweave 生成​​输出。我在您的代码中没有看到大量的 LaTeX,因此 Knitr 包可能更适合您的目的。 Knitr 能够输出 PDF 和 HTML 文档。 2.“预期情节”和“列表情节”链接失效。
  • 感谢zhaoy的评论。我更正了代码以与 knitr 一起使用。我不知道为什么这些数字的链接不能直接工作。但是,如果您右键单击并在新选项卡中打开图像,图像似乎就在那里。

标签: r ggplot2 rstudio knitr xtable


【解决方案1】:

我不知道为什么geom_segment 中的水平线从一个情节“移动”到另一个情节,而不是跨越xmeanxqtl。但是,我能够通过从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))
}

【讨论】:

  • 感谢您花时间解决问题 eipi10 :) 您的解决方案适用于 x 轴上的问题。我尝试对 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 &lt;- data.frame(y_max-(10*yscale))x_coords &lt;- data.frame(c(xmean, xqtl)),就在循环内的语句 y &lt;- ggplot( ... 之前。问题依然存在..
【解决方案2】:

您可能想要使用 R Markdown 和 knitr,这比使用 LaTeX 和 R 更容易(也如 zhaoy 建议的那样)。

您可能还想查看ReporteRs 包。我认为它实际上比 knitr 更容易使用。但是,您不能使用它生成 PDF。但是您可以使用 pandoc 将它们转换为 PDF。

【讨论】:

  • 我发现 OP 的代码在 knitrRStudio 中运行良好,完全按照预期创建了一个 PDF 文件。水平线的位置不正确似乎不是knitr 问题,因为无论我以交互方式运行代码还是通过knitr 运行代码都会发生这种情况。
  • 谢谢坎儿。我将试用 ReporteRs 软件包。然而,正如 eipi 所说,代码似乎与 knitr 和 Rstudio 配合得很好,除了水平线。我会尽快试用 ReporteRs
猜你喜欢
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 2017-06-28
  • 2014-02-19
  • 2012-12-14
  • 2015-08-12
  • 2019-04-30
  • 2014-02-24
相关资源
最近更新 更多