【问题标题】:ggplot2 overwrites plots when saving in a listggplot2 保存在列表中时覆盖绘图
【发布时间】:2018-02-14 17:17:15
【问题描述】:

我有一个代码可以从数据框中绘制一些数据。 当我在没有循环的情况下运行代码时,它可以工作,但是当我使用代码然后执行 plots[[1]] plots[[2]] 时,所有图都是相同的,但实验室不同。

我做错了什么?谢谢

#-- Plots
plots <- list()
combinations <- combn(dim(ssgsea.diff)[2],2)

for (i in 1:dim(combinations)[2]){

  fit <- lm(ssgsea.diff[,combinations[1,i]] ~ ssgsea.diff[,combinations[2,i]], 
            data = ssgsea.diff)

  plot1 <- ggplot(ssgsea.diff) + 
    aes(ssgsea.diff[,combinations[1,i]], ssgsea.diff[,combinations[2,i]]) + 
    geom_point()

  plot1 <- plot1 + 
    labs(x = names(ssgsea.diff)[combinations[1,i]], 
         y = names(ssgsea.diff)[combinations[2,i]]) + 
    geom_smooth(method="lm", col = "red") + 
    labs(title = paste("Adj R2 = ", signif(summary(fit)$adj.r.squared, 5), 
                       " Slope =",signif(fit$coef[[2]], 5), 
                       " Pval =",signif(summary(fit)$coef[2,4], 5)))

  plots[[i]] <- plot1
}

【问题讨论】:

  • 您能以dput() 的形式提供这里使用的数据集吗?或者,使用来自datasets 包的常见数据集之一使此问题可重现。
  • 我无法提供数据集。但基本上,代码中有一些东西,保存在列表plots 中的所有图看起来就像最后创建的图。即使代码在循环外工作,也会发生这种情况。

标签: r ggplot2


【解决方案1】:

由于没有提供数据,我将尝试使用 R 中的通用数据集进行演示:

data(airquality)
ssgsea.diff <- as.data.frame(airquality)

plots <- list()
combinations <- combn(dim(ssgsea.diff)[2],2)

重现使用原始代码的问题。 for 循环完成后有 15 个图,实际上它们都使用不同的标签共享同一个图:

for (i in 1:dim(combinations)[2]){

  fit <- lm(ssgsea.diff[,combinations[1,i]] ~ ssgsea.diff[,combinations[2,i]], 
            data = ssgsea.diff)

  plot1 <- ggplot(ssgsea.diff) + 
    aes(ssgsea.diff[,combinations[1,i]], ssgsea.diff[,combinations[2,i]]) + 
    geom_point()

  plot1 <- plot1 + 
    labs(x = names(ssgsea.diff)[combinations[1,i]], 
         y = names(ssgsea.diff)[combinations[2,i]]) + 
    geom_smooth(method="lm", col = "red") + 
    labs(title = paste("Adj R2 = ", signif(summary(fit)$adj.r.squared, 5), 
                       " Slope =",signif(fit$coef[[2]], 5), 
                       " Pval =",signif(summary(fit)$coef[2,4], 5)))

  plots[[i]] <- plot1
}

解决方案下面将导致 15 个不同的图存储在列表中(我还首先定义了列索引,以使代码更具可读性):

for (i in 1:dim(combinations)[2]){

  # define column indices & column names first
  C1 <- combinations[1, i]; C1.name <- names(ssgsea.diff)[C1]
  C2 <- combinations[2, i]; C2.name <- names(ssgsea.diff)[C2]

  fit <- lm(ssgsea.diff[, C1] ~ ssgsea.diff[, C2]) # no need to specify data here

  plot1 <- ggplot(ssgsea.diff) + 
    aes_string(C1.name, C2.name) + geom_point()

  plot1 <- plot1 + 
    labs(x = C1.name, y = C2.name) + 
    geom_smooth(method="lm", col = "red") + 
    labs(title = paste("Adj R2 = ", signif(summary(fit)$adj.r.squared, 5), 
                       " Slope =", signif(fit$coef[[2]], 5), 
                       " Pval =", signif(summary(fit)$coef[2, 4], 5)))

  plots[[i]] <- plot1
}

rm(C1, C2, C1.name, C2.name, fit, plot1, i)

说明:由于您为 ggplot 指定美学映射的方式,所有绘图对象都在循环结束时评估,当前(即最后一个)值为 i。更安全的方法是利用 ggplot 中的 data 参数,它将数据框存储在 ggplot 对象本身中作为 copy 而不是 reference。当i 在每个循环中发生变化时,ggplot 对象中的数据副本不会发生变化。这两个帖子中的答案进一步讨论了这个问题:Storing ggplot objects in a list from within loop in R & Storing plot objects in a list

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-20
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多