for 循环与 ggplots 生成具有相同值但不同标题的图形

Har*_*rry 5 for-loop r ggplot2 cowplot

我已经阅读了很多关于使用循环为 ggplot 生成大量图表的帖子,但找不到任何可以解释我的问题的帖子......

我有一个数据框,正在尝试遍历 92 列,为每列创建一个新图形。我想将每个图保存为一个单独的对象。当我运行我的循环(下面的代码)并打印图形时,所有图形都是正确的。但是,当我使用assign() 更改print() 命令时,图形不正确。标题正在发生变化,但图形值都是相同的(它们都是最终图形的值)。我发现了这一点,因为当我使用 plot_grid() 生成 10 个图时,图形标题和轴标签都是正确的,但值是相同的!

我的数据集很大,所以我提供了一个小数据集用于下面的说明。

示例数据名:

library(ggplot)
library(cowplot)
df <- as.data.frame(cbind(group=c(rep("A", 4), rep("B", 4)), a=sample(1:100, 8), b=sample(100:200, 8), c=sample(300:400, 8))) #make data frame
cols <- 2:4 #define columns for plots
for(i in 1:length(cols)){
  df[,cols[i]] <- as.numeric(as.character(df[,cols[i]]))
} #convert columns to numeric
Run Code Online (Sandbox Code Playgroud)

情节:

for (i in 1:length(cols)){
  g <- ggplot(df, aes(x=group, y=df[,cols[i]])) +
    geom_boxplot() +
    ggtitle(colnames(df)[cols[i]])
  print(g)
  assign(colnames(df)[cols[i]], g) #generate an object for each plot
}

plot_grid(a, b, c)
Run Code Online (Sandbox Code Playgroud)

我在想,当 ggplots 绘制绘图时,它只呈现 i 的最终值中的数据?或者类似的东西?有没有解决的办法?

我希望这样做,因为我希望制作很多图形,然后我想混合和匹配图形的图。

谢谢!

bap*_*ste 2

有两种标准方法可以处理此问题:

1- 使用长格式 data.frame

2- 用于aes_string引用宽格式 data.frame 中的变量名称

以下是可能策略的说明。

library(ggplot2)
library(gridExtra)

# data from other answer
df <- data.frame(group=c(rep("A", 4), rep("B", 4)),
                 a=sample(1:100, 8),
                 b=sample(100:200, 8),
                 c=sample(300:400, 8))

## first method: long format
m <- reshape2::melt(df, id = "group")
p <- ggplot(m, aes(x=group, y=value)) +
    geom_boxplot() 

pl <- plyr::dlply(m, "variable", function(.d) p %+% .d + ggtitle(unique(.d$variable)))
grid.arrange(grobs=pl)

## second method: keep wide format
one_plot <- function(col = "a")  ggplot(df, aes_string(x="group", y=col)) +  geom_boxplot() + ggtitle(col)
pl <- plyr::llply(colnames(df)[-1], one_plot)
grid.arrange(grobs=pl)

## third method: more explicit looping

pl <- vector("list", length = ncol(df)-1)
for(ii in seq_along(pl)){
  .col <- colnames(df)[-1][ii]
  .p <- ggplot(df, aes_string(x="group", y=.col)) +  geom_boxplot() + ggtitle(.col)
  pl[[ii]] <- .p
}

grid.arrange(grobs=pl)
Run Code Online (Sandbox Code Playgroud)

有时,当将 ggplot 调用包装在函数/for 循环内时,会面临局部变量的问题(这里不是这种情况,如果aes_string使用的话)。在这种情况下,我们可以定义一个本地环境

请注意,使用类似的构造aes(y=df[,i])可能看起来可行,但可能会产生非常错误的结果。考虑一个多面图,data.frame 将被分成每个面板的不同组,如果直接传递数值而不是aes()变量名称,则此子集可能无法对正确的数据进行分组。