【问题标题】:For loop to create a list of ggplots always save the same coordinates for points and segmentsFor循环创建ggplots列表总是为点和段保存相同的坐标
【发布时间】:2019-01-31 15:53:57
【问题描述】:

首先你需要加载这些包:

library(ggplot2)
library(ggrepel)

我有一个这样的数据框“dframe”:

V1          V2           V3          V4          V5          V6          V7          Groups
0.05579838 -0.44781204 -0.164612982 -0.05362210 -0.23103516 -0.04923499 -0.06634579      1
0.14097924 -0.35582736  0.385218841  0.18004788 -0.18429327  0.29398646  0.69460669      2
0.10699838 -0.38486299 -0.107284020  0.16468591  0.48678593 -0.70776085  0.20721932      3
0.22720072 -0.30860464 -0.197930310 -0.24322096 -0.30969028 -0.04460600 -0.08420536      4
0.24872635 -0.23415141  0.410406163  0.07072146 -0.09302970  0.01662256 -0.21683816      5
0.24023670 -0.27807097 -0.096301697 -0.02373198  0.28474825  0.27397862 -0.29397324      6
0.30358363  0.05630646 -0.115190308 -0.51532428 -0.08516130 -0.08785924  0.12178198      7
0.28680386  0.07609196  0.488432908 -0.13082951  0.00439161 -0.17572986 -0.25854047      8
0.30084361  0.06323714 -0.008347161 -0.26762137  0.40739524  0.22959024  0.19107494      9
0.27955675  0.22533959 -0.095640072 -0.27988676 -0.04921808 -0.10662521  0.19934074     10
0.25209125  0.22723231  0.408770841  0.13013867 -0.03850484 -0.23924023 -0.16744745     11
0.29377963  0.13650247 -0.105720288 -0.00316556  0.29653723  0.25568169  0.06087608     12
0.24561895  0.28729625 -0.167402464  0.24251060 -0.22199262 -0.17182828  0.16363196     13
0.25150342  0.25298115 -0.147945172  0.43827820  0.02938933  0.01778563  0.15241257     14
0.30902922 -0.01299330 -0.261085058  0.13509982 -0.40967529 -0.11366113 -0.06020937     15
0.28696274 -0.12896680 -0.196764195  0.39259942  0.08362863  0.25464125 -0.29386260     16

这是一个可重现的数据框,您可以从 Mark Peterson 那里使用:

dframe <-
  rnorm(70) %>%
  matrix(nrow = 10) %>%
  as_tibble() %>%
  setNames(paste0("V", 1:ncol(.))) %>%
  mutate(Groups = 1:nrow(.)
         , Label = 1:nrow(.))

我创建了一个我想从我的数据框中使用的列组合表:

#Create all possible combinations
combs<-expand.grid(seq(7),seq(7))
#Remove duplicate and order
combs<-combs[combs$Var1 != combs$Var2,]
combs<-combs[order(combs[,1]),]

然后我做了一个 for 循环,应该生成一个 ggplots 列表,1 个组合图:

list_EVplots<-list()
  for(i in seq(nrow(combs))){
    list_EVplots[[paste(combs[i,1],"&",combs[i,2])]]<- ggplot(data=dframe) +
      ggtitle(paste("Eigenvector Plot - Pairwise",
                    "correlation with","adjustment")) +
      geom_point(aes(x = dframe[,combs[i,1]], y = dframe[,combs[i,2]],
                     color = Groups)) +
      geom_segment(aes(x = rep(0,nrow(dframe)), y = rep(0,nrow(dframe)),
                       xend = dframe[,combs[i,1]], yend = dframe[,combs[i,2]],
                       color = Groups),
                   size = 1, arrow = arrow(length = unit(0.3,"cm"))) +
      geom_label_repel(aes(x = dframe[,combs[i,1]], y = dframe[,combs[i,2]],
                           label = rownames(dframe))) +
      scale_color_manual(values=colors) +
      xlab(paste0("Eigenvector ",combs[i,1])) +
      ylab(paste0("Eigenvector ",combs[i,2])) +
      theme(plot.title = element_text(hjust = 0.5),
            axis.title = element_text(size = 13),
            legend.text = element_text(size=12)) +
      geom_hline(yintercept = 0, linetype="dashed") +
      geom_vline(xintercept = 0, linetype="dashed")
  }

运行此 for 循环后,我获得了我的列表“list_EVplots”。 问题:迭代似乎适用于 xlab() 和 ylab(),它也适用于列表中的绘图名称,但 geom_point(aes()) 和 geom_segment(aes()) 的坐标不会改变。当它们显然应该改变时,坐标保持不变! 我认为坐标保持锁定在用于第一次迭代的第一个绘图的坐标上。 如果有人对此有解决方案,我将非常感谢您的帮助。

使用 R Studio 在 Linux 16.04 下工作。 R 版本 3.5.2 (2018-12-20) -- “蛋壳冰屋”

我尝试使用仅包含我想要使用的列的子集数据框,而不是使用 8 列数据框:没有用。

预期:列表应包含不同的图:所有图都应不同。

问题:所有图在列表中的点和线段坐标相同。

【问题讨论】:

  • 您能否提供一个reproducible 示例,以便人们在发布之前测试他们的答案?对于您的问题,我的第一个猜测是使用ggplotGrob 函数,即将ggplot() + ... 的输出转换为grob,然后再将其分配给list_EVplots[[paste(combs[i,1],"&amp;",combs[i,2])]]
  • 我认为它是可重现的。你能告诉我你缺少什么吗?然后我可以进行相应的编辑。
  • 好的,所以从dput() 输出的样本数据会很好。如果您尝试尽可能减少代码以重现问题,这总是有帮助的。现在我收到错误could not find function "geom_label_repel"。在减少你的代码以省略这个缺失的函数后,我得到Error: 'data' must be uniquely named but has duplicate columns
  • @MRau 我编辑了帖子。希望对您有所帮助!

标签: r for-loop ggplot2


【解决方案1】:

最简单的答案往往是最简单的:尽量避免在lapply 更合适的地方使用for 循环。我在您的代码中没有看到任何明显的迹象表明问题出在哪里,但我猜这是深度嵌套的 [] 语句中的问题。

这是一种使用lapplyaes_string 处理变量的方法。如果您想要的不是完整的成对图集,您可能需要稍微修改对两个 lapply 的调用。

首先,一些可重现的数据(使用dplyr 制作)。请注意,我明确指定了Labels,而不是依赖行名(这是一种很好的做法,并且在调用ggplot 时更容易使用)。

dframe <-
  rnorm(70) %>%
  matrix(nrow = 10) %>%
  as_tibble() %>%
  setNames(paste0("V", 1:ncol(.))) %>%
  mutate(Groups = 1:nrow(.)
         , Label = 1:nrow(.))

然后,我将提取您要用于绘图的列。我正在命名它们,以便返回的列表具有自动分配的列名。

my_cols <-
  names(dframe)[1:7] %>%
  setNames(.,.)

然后,只需设置一个嵌套的lapply 来处理所有成对比较:

plot_list <-
  lapply(my_cols, function(col1){
    lapply(my_cols, function(col2){

      if(col1 == col2){
        return(NULL)
      }

      ggplot(dframe) +
        ggtitle(paste("Eigenvector Plot - Pairwise",
                      "correlation with","adjustment")) +
        geom_point(aes_string(x = col1
                              , y = col2
                              , color = "Groups")) +
        geom_segment(aes_string(xend = col1
                                , yend = col2
                                , color = "Groups")
                     , x = 0
                     , y = 0
                     , size = 1
                     , arrow = arrow(length = unit(0.3,"cm"))) +
        geom_label_repel(aes_string(x = col1
                                    , y = col2
                                    , label = "Label")) +
        xlab(paste0("Eigenvector ", col1)) +
        ylab(paste0("Eigenvector ", col2)) +
        theme(plot.title = element_text(hjust = 0.5),
              axis.title = element_text(size = 13),
              legend.text = element_text(size=12)) +
        geom_hline(yintercept = 0, linetype="dashed") +
        geom_vline(xintercept = 0, linetype="dashed")

    })
  })

请注意,您没有包含要用于组的颜色,因此我保留了默认值。

绘图正确显示,这应该更容易完成。

【讨论】:

  • “哦,嗨,马克!” - 不认真:非常感谢您的精彩回答。我将它改编为我的代码,现在它工作得很好。我承认我不是 dplyr 的忠实粉丝,我更喜欢 data.table 的解决方案,但我不会挑剔,它做得很好。所以对你来说,问题来自 ggplot 对吗?再次感谢。
  • 我认为这个问题是由于试图将数据——而不是列名——传递给 ggplot 引起的。这似乎经常导致麻烦。
  • 是的,我同意,但我不明白为什么我只在绘图中使用的坐标上遇到迭代问题,而不是在轴标签中。就好像 ggplot 只能迭代自身的一部分。如果真是这样的话,我遇到的问题毕竟听起来不是那么的小事。
  • 我玩了更多,它似乎使用了icurrent 值的坐标。如果您更改i 的值,您将获得与该索引匹配的图。 ggplot 对象在渲染之前不会评估数据参数,此时它正在获取i 的当前全局值。 xlab 和 ylab 函数显然不是这样。如果您更仔细地检查 ggplot 对象(例如,使用 str(list_EVplots[[1]])),您可以看到其中的一些内容
猜你喜欢
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多