【问题标题】:Changing ggtitle in a loop [closed]在循环中更改 ggtitle [关闭]
【发布时间】:2019-08-05 11:40:49
【问题描述】:

我想根据一个变量的值对我的数据集进行子集化,并以该变量的值作为绘图名称和 ggtitle 绘制一个 ggplot 并保存每个绘图。

最后,我想将所有图表合并到一个页面中。

这是一个简化的例子。

y=rnorm(100, 0,1)
x=sample(100, 5, replace = T)

k=5
z=sample(k, 100, replace=T)

z <- factor(z, levels = c(1,2,3,4,5),
                    labels = c("red", "blue", "green", "purple", "yellow"))

dat=data.frame(y=y, x=x, z=z)
library(ggplot2)

for(i in seq_len(k))
{
dat2 = data.frame(dat[dat$z=='i',])

i <- ggplot(dat2, aes(x=x, y=y)) +
  geom_point() +
  ggtitle(i)
}

library(gridExtra)
grid.arrange(red, blue, green, purple,yellow, nrow = 2)

我无法将变量保存为 i 并与 ggtitle() 保持一致。每个图表的标题应该是不同的颜色:红色,蓝色,绿色......等。

谢谢。

【问题讨论】:

  • dat[dat$z=='i',] 应该是 dat[dat$z==i,] 以使您的代码正常工作。为什么在循环中将绘图分配给i?这很令人困惑。无论如何,您的整个代码都可以通过单行调用来替换以添加方面:)
  • 哦,我刚刚意识到您想要通过i &lt;- ggplot(...) 实现的目标!那是行不通的——我会更新我的答案。

标签: r loops ggplot2


【解决方案1】:

您的子集不正确:您使用了字符串 'i' 而不是变量 i

您可以简单地使用构面来代替 for 循环和 grid.arrange

dat=data.frame(y=y, x=x, z=z)
ggplot(dat, aes(x = x, y = y)) + 
  geom_point() + 
  facet_wrap(~ z)

如果要循环排列,需要使用列表:

plots <- list()

for(z in levels(z)) {
  dat2 = data.frame(dat[dat$z==z,])

  plots[[z]] <- ggplot(dat2, aes(x=x, y=y)) +
    geom_point() +
    ggtitle(z)
}

library(gridExtra)
grid.arrange(plots$red, plots$blue, plots$green, plots$purple, plots$yellow, nrow = 2)

请注意,我使用 z 的值作为循环变量,而不是 1:5

这样做更优雅:

colors <- c("red", "blue", "green", "purple", "yellow")
N <- 100

dat <- data.frame(x = sample(N, 5, replace = T),
                  y = rnorm(N, 0,1),
                  z = sample(colors, N, replace=T))

plot_color <- function(col, dat) {
  dat2 <- dat[dat$z==col,]

  ggplot(dat2, aes(x=x, y=y)) +
    geom_point() +
    ggtitle(col)
}

plots <- purrr::map(colors, plot_color, dat = dat)
do.call(grid.arrange, c(plots, nrow = 2))

【讨论】:

  • 是的,对于这个例子,它会起作用,但在我的原始代码中,每个子集的图表略有不同。因此,很难一次性生成图表。
  • @Stata_user 如果它们不是同一张图,我不确定在循环中创建它们是否有意义。你最终会得到if (i == "red") {...} else if (i == "green") {...},这是一个完整的反模式。
  • 感谢@antoine-sac。我做了这样的事情。它现在似乎可以工作了。
【解决方案2】:

您可以使用 for 循环,也可以使用组合 lapply/do.call 更短更快地执行此操作;

myplots = lapply(seq_len(k), function(i){
    p <- ggplot(data.frame(dat[dat$z==i,]), aes(x=x, y=y)) +
        geom_point() +
        ggtitle(i)
    ggsave(paste0(i,'.png'),p)        # if you want to save each plot
    return(p)
})
do.call(grid.arrange, myplots) 

在环境中拥有单独的地块

names(myplots) = seq_len(k)
list2env(myplots)

或单独执行此操作(例如在循环/lapply 内);

assign('blue',myplots[[1]])

【讨论】:

  • 不,抱歉仍然没有。正如我之前提到的,我不能将所有结果集中到一个数据框中。我需要 1. 到子集 2. 操作数据(此处未显示),然后才需要 3. 图表。我最大的问题是将值标签作为每个图表的标题。
  • 很抱歉,您的问题不清楚。如果您不能将其中的所有数据放在一个数据框中,您希望如何进行子集化?是否要列出适当的数据帧(并替换 seq_len(k))?您想在绘图函数中添加 if 语句吗?如果所有图表都不同,为什么要使用循环?也许这会对您有所帮助:stackoverflow.com/questions/18747091/…。答案还显示了如何按照您的要求将值标签设置为 ggtitle。我编辑了我的答案。
猜你喜欢
  • 1970-01-01
  • 2020-09-17
  • 2020-07-27
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多