R knitr Markdown: 如何在 For 循环中输出图形

77
我想创建一个自动化的knitr报告,可以为数据框中的每个数值字段生成直方图。我的目标是在不指定实际字段的情况下完成此操作(此数据集包含超过70个字段,并且我还希望重用脚本)。
我尝试了几种不同的方法:
- 将图形保存到对象“p”中,然后在循环后调用“p” - 这只会绘制最终的图形 - 创建一个图表数组“PLOTS <- NULL”,并在循环中添加图表“PLOTS <- append(PLOTS, p)” - 在循环外部访问这些图表根本不起作用 - 甚至尝试将每个保存到“.png”文件中,但宁愿不必处理保存和重新访问每个文件的开销
我担心绘图设备的复杂性超出了我的能力。
问题:如何使以下代码块将循环中的每个图都输出到报告中?目前,我能做到的最好的是通过将其保存到对象并在循环外调用该对象来输出最终图形的输出。
RStudio中使用knitr的R markdown代码块:
```{r plotNumeric, echo=TRUE, fig.height=3}
suppressPackageStartupMessages(library(ggplot2))
FIELDS <- names(df)[sapply(df, class)=="numeric"]
for (field in  FIELDS){
  qplot(df[,field], main=field)  
}
```

从这个点开始,我希望进一步定制绘图。


是的,我必须承认我对此很新... - bnjmn
我已经在你的问题和标题中添加了knitr标签,以明确你正在使用它。 - David Robinson
9
你是不是忘记在qplot外面加上print了?如果qplot不在循环内,knitr会自动为你添加print,但(至少我安装的版本)无法检测到循环内部的情况(这与R命令行的行为一致)。 - cbeleites unhappy with SX
1
@cbeleites 你应该把这个作为答案,这样 OP 就可以接受它了。 - sebastian-c
遇到了类似的问题。尝试将分析和 ggplot 图形循环到 .Rmd 文件中。但是在循环运行后,没有任何图形或分析输出被打印出来。有什么想法吗? - I Del Toro
5个回答

65

qplot包装在print中。

如果qplot在循环外部,knitr将为您完成此操作,但(至少我安装的版本)不会在循环内部检测到这一点(这与R命令行的行为一致)。


1
遇到了类似的问题。尝试将分析和 ggplot 图形循环到 .Rmd 文件中。但是在循环运行后,没有任何图形或分析输出被打印出来。有什么想法吗? - I Del Toro
1
有人能解释一下为什么你必须包装整个东西而不是只在最后管道输出吗?例如 ggplot(......) %>% print() - jzadra
1
@jzadra:你也可以这样做。但是,为了使管道正常工作,您仍需要将(ggplot() + geom_*())括在括号中 - 否则,由于运算符优先级,您只会得到添加到ggplot的最后一个对象的打印输出。(至于为什么答案中没有这个:当我写下那个答案时,还没有出现管道)。 - cbeleites unhappy with SX
如果我们使用 dygraph() R 函数而不是 qplot,它就无法正常工作。 - Lazarus Thurston
lapplytagList方法以更通用和健壮的方式解决了这个问题。请在此处查看解决方案。 https://dev59.com/BF0a5IYBdhLWcg3wS2-8#35235069 - Lazarus Thurston
显示剩余2条评论

27

想要添加一个快速提示: 不知何故我谷歌了同样的问题并进入了这个页面。 现在在2018年,只需在循环中使用print()

for (i in 1:n){
...
    f <- ggplot(.......)
    print(f)
}

1
这就是字面上的意思,即“在print中包装qplot”,也就是重新陈述了已接受的答案。 - merv
12
直接查看代码有助于理解,因为它可以将抽象的概念直观地呈现出来。 - Peter
3
这对于初学者很容易理解,而采纳的答案则不然。因此,这个回答更好。 - monkey

11

我在Markdown中使用子Rmd文件,也可以在Sweave中使用。

在Rmd中使用以下代码片段:

```{r run-numeric-md, include=FALSE}
out = NULL
for (i in c(1:num_vars)) {
  out = c(out, knit_child('da-numeric.Rmd'))
}
```

da-numeric.Rmd看起来像:

Variabele `r num_var_names[i]`
------------------------------------

Missing :  `r sum(is.na(data[[num_var_names[i]]]))`  
Minimum value : `r min(na.omit(data[[num_var_names[i]]]))`  
Percentile 1 : `r quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[2]`  
Percentile 99 : `r quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[100]`  
Maximum value : `r max(na.omit(data[[num_var_names[i]]]))`  

```{r results='asis', comment="" }
warn_extreme_values=3
d1 = quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[2] > warn_extreme_values*quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[1]
d99 = quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[101] > warn_extreme_values*quantile(na.omit(data[[num_var_names[i]]]),probs = seq(0, 1, 0.01))[100]
if(d1){cat('Warning : Suspect extreme values in left tail')}
if(d99){cat('Warning : Suspect extreme values in right tail')}
```

``` {r eval=TRUE,  fig.width=6, fig.height=2}
library(ggplot2)

v <- num_var_names[i]
hp <- ggplot(na.omit(data), aes_string(x=v)) + geom_histogram( colour="grey", fill="grey", binwidth=diff(range(na.omit(data[[v]]))/100))

hp + theme(axis.title.x = element_blank(),axis.text.x = element_text(size=10)) + theme(axis.title.y = element_blank(),axis.text.y = element_text(size=10))

```

请在Github上查看我的datamineR包https://github.com/hugokoopmans/dataMineR


嘿 :) knit_child() 函数是从哪里来的? - Fabian
这样做可以更灵活地创建图标题并添加其他细节,而不仅仅是接受的答案。您可以使用选项“fig.caption”并更改每个循环迭代的块名称。 - Ricecakes
1
能否引用针织标签而不是单独的文件? - user3072843

3
作为对Hugo出色答案的补充,我认为在2016年你需要包含一个“print”命令:print command as well:
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in c(1:num_vars)) {
  out = c(out, knit_child('da-numeric.Rmd'))
}

`r paste(out, collapse = '\n')`
```

0

对于将Rmd编织成HTML,我发现拥有一个图表列表更加方便。在这种情况下,我可以通过使用results='hide'来获得期望的输出,具体如下:

---
title: "Make a list of figures and show it"
output: 
  html_document
---


```{r}
suppressPackageStartupMessages({
  library(ggplot2)
  library(dplyr)
  requireNamespace("scater")
  requireNamespace("SingleCellExperiment")
})
```


```{r}
plots <- function() {
  print("print")
  cat("cat")
  message("message")
  warning("warning")
  
  # These calls generate unwanted text
  scater::mockSCE(ngene = 77, ncells = 33) %>%
    scater::logNormCounts() %>%
    scater::runPCA() %>%
    SingleCellExperiment::reducedDim("PCA") %>%
    as.data.frame() %>%
    {
      list(
        f12 = ggplot(., aes(x = PC1, y = PC2)) + geom_point(),
        f22 = ggplot(., aes(x = PC2, y = PC3)) + geom_point()
      )
    }
}
```

```{r, message=FALSE, warning=TRUE, results='hide'}
plots()
```

只有图表和警告信息(您可以关闭)会显示出来。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接