美文网首页R优质资源RR
为什么for循环和aes八字不合

为什么for循环和aes八字不合

作者: 小洁忘了怎么分身 | 来源:发表于2020-04-17 11:59 被阅读0次

    前面写过这篇:批量绘制箱线图https://www.jianshu.com/p/ec9034fe9a2c
    今天发现了新问题。是aes和for循环的八字不合的诡异现象,来分析一下大家看看,能不能破:

    1.示例数据

    mat <- matrix(rnorm(60),nrow=10)
    colnames(mat)=paste0('sample',1:6)
    rownames(mat)=paste0('gene',1:10)
    library(ggplot2)
    mat2 <- t(mat)
    mat2 <- data.frame(mat2) 
    mat2$group=rep(c('A','B'),each=3)
    

    mat2长这样:


    我们的目的是对对每一个基因画箱线图,这可以通过gather+分面或者for循环+aes_string来实现,这个没有问题。

    尝试1:当不用for循环的时候

    p1 = ggplot(data=mat2)+
      geom_boxplot(aes(x=group,y=mat2[,1],color = group))
    p2 = ggplot(data=mat2)+
      geom_boxplot(aes(x=group,y=mat2[,2],color = group))
    library(patchwork)
    p1+p2
    

    成功了。

    尝试2:把1和2替换成i,传参试试

    i=1
    p1 = ggplot(data=mat2)+
      geom_boxplot(aes(x=group,y=mat2[,i],color = group))
    i=2
    p2 = ggplot(data=mat2)+
      geom_boxplot(aes(x=group,y=mat2[,i],color = group))
    library(patchwork)
    p1+p2
    

    所以放进for循环也是一样的,会出10张一样的图

    p=list()
    for(i in 1:10){
      p[[i]]=ggplot(data=mat2)+
        geom_boxplot(aes(x=group,y=mat2[,i],color = group))
    }
    wrap_plots(p,nrow=2,guides = 'collect')
    

    所有图都一样,所以失败了。

    尝试3:换apply试试呢?

    p = apply(mat2[,1:10], 2, function(i){
      ggplot(data=mat2)+
        geom_boxplot(aes(x=group,y=i,color = group))
    })
    wrap_plots(p,nrow=2,guides = 'collect')
    

    所以你说,aes它不能传参吗?是不能,大佬们说需要传参就改成aes_string,它确实可以。但我好奇是为什么apply就能做出来。可能是因为它的循环方式和for循环不一样?

    把这个apply的循环方式原样替换到for循环里,仍然是不行的:

    p = list()
    n = 0
    for(i in mat2[,1:10]){
      n = n+1
      p[[n]]=ggplot(data=mat2)+
        geom_boxplot(aes(x=group,y=i,color = group))
    }
    wrap_plots(p,nrow=2,guides = 'collect')
    

    经过这样的尝试,我觉得问题应该在于aes传参数有一点问题。for循环涉及到每次y映射的改变,所以就不行。

    But,如果我非要用for循环实现呢?

    什么叫倔强,可能我撞了南墙才会回头吧,可能我见了黄河才会死心吧~aaa,想用,那就是有办法的。实在不行,我们每次改完数据再作图就好了!

    一个知识点,当gene这一列不存在于mat2的时候,mat2$gene = i表示新增一列,列名为gene,内容为i。当gene这一列存在于mat2的时候,mat2$gene = i表示修改gene这一列的内容,改为i。

    p = list()
    n = 0
    for(i in mat2[,1:10]){
      n = n+1
      mat2$gene = i
      p[[n]]=ggplot(data=mat2)+
        geom_boxplot(aes(x=group,y=gene,color = group))
    }
    wrap_plots(p,nrow=2,guides = 'collect')
    

    一个意义不大的问题引起了我的兴趣,两个小时又木有了。没办法,谁叫我对R语言兴趣至深,爱得深沉 哈哈。

    当你即将放弃,其实彼岸已经在眼前

    小郭发来aes帮助文档里的一段例子:



    我们都在惊叹,两个叹号是什么操作???

    p=list()
    for(i in 1:10) {
      p[[i]] = ggplot(data = df, aes(x = group, y = !!df[, i])) +
        geom_boxplot(aes(color = group))
    }
    library(patchwork)
    wrap_plots(p, nrow = 2, guides = 'collect')
    

    问题就这么解决了!你说诡异不诡异。ggplot2博大精深,大佬们玩的很深沉,表示十分佩服。
    ps:你会看到每种方法出来的列名都是不一样的,但那个可以改,加个labels参数就行了。

    相关文章

      网友评论

        本文标题:为什么for循环和aes八字不合

        本文链接:https://www.haomeiwen.com/subject/yarevhtx.html