“for”循环只添加最终的ggplot图层

“for”循环只添加最终的ggplot图层

简介:当我使用“for”循环将图层添加到小提琴图(在ggplot中)时,添加的唯一图层是由最终循环迭代创建的图层。然而,在模拟循环将生成的代码的显式代码中,添加了所有层。


详细信息:我正在尝试创建具有重叠层的小提琴图,以显示估计分布对于多个调查问题响应重叠或不重叠的程度,按地点分层。我希望能够包含任意数量的地方,因此每个地方我都有一列数据框,并且我尝试使用“for”循环来为每个地方生成一个ggplot图层。但是循环只会从循环的最后一次迭代中添加该层。


此代码说明了问题,以及一些失败的建议方法:


library(ggplot2) 


# Create a dataframe with 500 random normal values for responses to 3 survey questions from two cities

topic <- c("Poverty %","Mean Age","% Smokers")

place <- c("Chicago","Miami")

n <- 500

mean <- c(35,  40,58,  50, 25,20)

var  <- c( 7, 1.5, 3, .25, .5, 1)

df <- data.frame( topic=rep(topic,rep(n,length(topic)))

                 ,c(rnorm(n,mean[1],var[1]),rnorm(n,mean[3],var[3]),rnorm(n,mean[5],var[5]))

                 ,c(rnorm(n,mean[2],var[2]),rnorm(n,mean[4],var[4]),rnorm(n,mean[6],var[6]))

                )

names(df)[2:dim(df)[2]] <- place  # Name those last two columns with the corresponding place name.

head(df) 


# This "for" loop seems to only execute the final loop (i.e., where p=3)

g <- ggplot(df, aes(factor(topic), df[,2]))

for (p in 2:dim(df)[2]) {

  g <- g + geom_violin(aes(y = df[,p], colour = place[p-1]), alpha = 0.3)

}

g


# But mimicing what the for loop does in explicit code works fine, resulting in both "place"s being displayed in the graph.

g <- ggplot(df, aes(factor(topic), df[,2]))

g <-   g + geom_violin(aes(y = df[,2], colour = place[2-1]), alpha = 0.3)

g <-   g + geom_violin(aes(y = df[,3], colour = place[3-1]), alpha = 0.3)

g


## per http://stackoverflow.com/questions/18444620/set-layers-in-ggplot2-via-loop , I tried 

g <- ggplot(df, aes(factor(topic), df[,2]))

for (p in 2:dim(df)[2]) {

  df1 <- df[,c(1,p)]

  g <- g + geom_violin(aes(y = df1[,2], colour = place[p-1]), alpha = 0.3)

}

g

# but got the same undesired result

沧海一幻觉
浏览 1291回答 3
3回答

qq_遁去的一_1

发生这种情况的原因是由于ggplot“懒惰评估”。当ggplot以这种方式使用时,这是一个常见的问题(将这些层分别放在一个循环中,而不是ggplot像你在@ hrbrmstr的解决方案中那样使用它)。ggplot将参数存储aes(...)为表达式,并仅在渲染绘图时对其进行求值。所以,在你的循环中,类似于aes(y&nbsp;=&nbsp;df[,p],&nbsp;colour&nbsp;=&nbsp;place[p-1])按原样存储,并在循环完成后渲染绘图时进行评估。此时,p = 3,因此所有图都以p = 3呈现。因此,执行此操作的“正确”方法是melt(...)在reshape2包中使用,以便将数据从宽格式转换为长格式,并让您ggplot管理图层。我把“正确”放在引号中,因为在这种特殊情况下有一个微妙之处。在使用融合数据框计算小提琴的分布时,ggplot使用总计(芝加哥和迈阿密)作为比例。如果你想要基于单独缩放频率的小提琴,你需要使用循环(遗憾地)。延迟评估问题的方法是在data=...定义中对循环索引进行任何引用。这不是作为表达式存储的,实际数据存储在绘图定义中。所以你可以这样做:g&nbsp;<-&nbsp;ggplot(df,aes(x=topic))for&nbsp;(p&nbsp;in&nbsp;2:length(df))&nbsp;{ &nbsp;&nbsp;gg.data&nbsp;<-&nbsp;data.frame(topic=df$topic,value=df[,p],city=names(df)[p]) &nbsp;&nbsp;g&nbsp;<-&nbsp;g&nbsp;+&nbsp;geom_violin(data=gg.data,aes(y=value,&nbsp;color=city))}g这会产生与你相同的结果。请注意,索引p不会显示在aes(...)。更新:关于scale="width"(在评论中提到)的说明。这导致所有小提琴具有相同的宽度(见下文),这与OP的原始代码中的缩放不同。IMO这不是一个可视化数据的好方法,因为它表明芝加哥集团有更多的数据。ggplot(gg)&nbsp;+geom_violin(aes(x=topic,y=value,color=variable), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alpha=0.3,position="identity",scale="width")

胡子哥哥

你可以做到没有循环:df.2 <- melt(df)gg <- ggplot(df.2, aes(x=topic, y=value))gg <- gg + geom_violin(position="identity", aes(color=variable), alpha=0.3)gg
打开App,查看更多内容
随时随地看视频慕课网APP