从循环中生成ggplots(并生成文件),而不用在RMarkdown中打印任何可见的输出 [英] Producing ggplots from a loop (and generating the files) without printing any visible output in RMarkdown

查看:184
本文介绍了从循环中生成ggplots(并生成文件),而不用在RMarkdown中打印任何可见的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建造一个混合了数字,文字和图表的表格。我用ggplot构建了我的图,然后将它们添加到表中(请参阅下面的代码)。因为我会(最终)有很多地块,所以我需要使用一个循环来有效地创建它们。但是,因为ggplot似乎需要打印才能为每个图形生成图像链接,所以我无法使用 invisible(),并随后得到讨厌的'[

解决方案

lapply 返回一个列表。当打印列表时,无论其内容如何,​​它还会打印列表索引 [[1]] [[2]] [[3]] ,....如果您改为保存列表, / p>

  plot_list < -  lapply(seq_along(score_set),FUN = function(x){plotgen(score_set [[x]],其他分数)})

然后在列表中打印每张图 而不是打印整个列表(我们可以用 invisible()>来包装返回的列表。 b
$ b

 不可见(lapply(plot_list,print))

它不会打印列表的索引。因为您将单独打印每个打印图,而不是打印恰好包含图的列表。






在一个简单的列表上演示:

  x = list(1,2,3)
print(x)
#[[ 1]]
#[1] 1

#[[2]]
#[1] 2

#[[3] ]
#[1] 3

隐形(lapply(x,print))
#[1] 1
#[1] 2
# [1] 3






另一种解决方案,不需要不可见因为它没有 return 任何东西,只是一个for循环:

  for(i in seq_along(plot_list))print(plot_list [[i]])

我会留给你看看你喜欢哪一个。




解决循环的会比较慢的担心:

  p = ggplot(mtcars,aes(x = hp,y = mpg))+ geom_point()
plist = list(p,p)

library(microbenchmark)
micro基准(
forloop = {for(i in seq_along(plist))print(plist [[i]])},
lapply =不可见(lapply(plist,print)),
times = 10L


#单位:毫秒
#expr分钟lq平均中位数uq max neval cld
#forloop 260.4532 271.2784 295.8415 276.1587 289.7507 402.1792 10 a
#lapply 258.8032 269.5915 296.2268 287.9524 294.8860 398.6803 10 a

差别是几毫秒。


I am building a table with a mixture of numbers, text, and plots. I constructed my plots with ggplot, and added them to the table afterwards (please see code below). Because I will (eventually) have many plots, I need to use a loop to efficiently create them all. However, because ggplot seems to require printing to generate image links for each plot, I am unable to use invisible(), and subsequently get the pesky '[1] [[2]] [[3]]' output at the top of the image below.

How can I compile the document without printing any visible output from ggplot?

```{r score_table, fig.show = "hide", echo = FALSE, fig.height=.75, fig.width=2.5}

#Load libraries
library(knitr)
library(ggplot2)

#Item data
items <- data.frame(text = sapply(1:3, FUN = function(x){
  paste0(sample(x = LETTERS, size = 60, replace = T), collapse = "")}))

#Score data
score_set = replicate(n = 3, expr = {data.frame(other = rep("other", 4),
  score=sample(1:7,4,TRUE))}, simplify = F)

#Plot function
plotgen<-function(score_set,other,score){
  p <- ggplot(score_set, aes(factor(other), score))
  p + geom_violin(fill = "#99CCFF") + coord_flip() + scale_x_discrete(name=NULL) +
    scale_y_continuous(breaks = round(seq(1, 7, by = 1),1), limits = c(1,7), name=NULL) +
    theme(axis.text.y=element_blank(),axis.title.y=element_blank(),axis.ticks.y=elemen    t_blank(),
          panel.grid.major.y = element_line(colour = "black"),
          panel.grid.minor = element_blank(),
          panel.background = element_rect(fill = "white"),
          panel.border = element_rect(colour = "black", fill=NA, size=1)) +
    geom_hline(yintercept=sample(1:7,1,TRUE), size = 1.5, colour = "#334466")
}

#Generate plots
print(lapply(seq_along(score_set), FUN = function(x){plotgen(score_set[[x]],other,score)}))

out <- cbind(row.names(items), as.character(items$text), sprintf("![](%s%s-%s.png)", 
       opts_current$get("fig.path"), opts_current$get("label"), 1:nrow(items)))

#Build table
kable(out, col.names = c("ID", "Text", "Scores"))
```

解决方案

lapply returns a list. When you print a list, regardless of it's contents, it also prints the list indices, [[1]], [[2]], [[3]], .... If you instead save the list,

plot_list <- lapply(seq_along(score_set), FUN = function(x){plotgen(score_set[[x]],other,score)})

and then print each plot in the list instead of printing the whole list (and this we can wrap in invisible() so the returned list isn't printed)

invisible(lapply(plot_list, print))

it won't print the indices of the list. Because you will be printing each plot individually, not printing a list which happens to contain plots.


Demonstrating on a simple list:

x = list(1, 2, 3)
print(x)
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2
# 
# [[3]]
# [1] 3

invisible(lapply(x, print))
# [1] 1
# [1] 2
# [1] 3


An alternate solution, not requiring invisible because it doesn't return anything, is just a for loop:

 for (i in seq_along(plot_list)) print(plot_list[[i]])

I'll leave it to you to see which you prefer.


Addressing the worry that a for loop would be slower:

p = ggplot(mtcars, aes(x = hp, y = mpg)) + geom_point()
plist = list(p, p)

library(microbenchmark)
microbenchmark(
    forloop = {for (i in seq_along(plist)) print(plist[[i]])},
    lapply = invisible(lapply(plist, print)),
    times = 10L
)

# Unit: milliseconds
#     expr      min       lq     mean   median       uq      max neval cld
#  forloop 260.4532 271.2784 295.8415 276.1587 289.7507 402.1792    10   a
#   lapply 258.8032 269.5915 296.2268 287.9524 294.8860 398.6803    10   a

The difference is a few milliseconds.

这篇关于从循环中生成ggplots(并生成文件),而不用在RMarkdown中打印任何可见的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆