与ggplots循环产生具有相同的值,但标题不同的图形 [英] for loop with ggplots produces graphs with identical values but different headings

查看:173
本文介绍了与ggplots循环产生具有相同的值,但标题不同的图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了很多有关使用循环ggplot生成大量的图形,但无法找到任何解释我的问题...

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

我的数据集很大,所以我提供了一个小数据集供下面的插图。



示例datafame:



<$ (gplot)
library(cowplot)
df < - as.data.frame(cbind(group = c(rep(A,4) ,rep(B,4)),a =样本(1:100,8),b =样本(100:200,8),c =样本(300:400,8)))#make data frame
cols < - 2:4#定义图表
(i in 1:length(cols)){
df [,cols [i]]< - as.numeric( as.character(df [,cols [i]]))
} #convert列转换为数字

图:

  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)#为每个plo生成一个对象t


plot_grid(a,b,c)

我在想,当ggplots作出阴谋,它只会呈现数据从我的最终价值?或者像那样的东西?有没有办法解决这个问题?



我希望这样做,因为有很多图我想做,然后我想混合和匹配图为数字。



谢谢!

解决方案

来处理这个问题:
$ b $ 1-使用一个长格式的数据框

2-使用 aes_string 指向宽格式data.frame中的变量名称

以下是可能的策略说明。












$ (b = 4),rep(B,4)),
a = sample(1:100,8),
b =样本(100:200,8),
c =样本(300:400,8))

##第一种方法:长格式
m< - reshape2 :: melt (df,id =group)
p <-ggplot(m,aes(x = group,y = value))+
geom_boxplot()

pl&l t; - plyr :: dlply(m,variable,function(.d)p%+%.d + ggtitle(unique(.d $ variable)))
grid.arrange(grobs = pl)

##第二种方法:保持宽格式
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)

##第三种方法:更明确地循环

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)


$ b有时,当在一个函数/ for循环中包装一个ggplot调用时,会面临局部变量的问题(这里不是这种情况,如果<$使用c $ c> aes_string )。在这种情况下,可以定义本地环境。注意,使用像 aes(y = df [,i])这样的结构可能会起作用,但是会产生非常错误的结果。 考虑一个多面的情节,data.frame将被拆分为不同的面板,这个子集可以失败惨败如果数字值直接传递给 aes()而不是变量名称,则将正确的数据分组。


I have read lots of posts about using loops for ggplot to generate lots of graphs, but cannot find any that explain my problem...

I have a dataframe and am trying to loop over 92 columns, creating a new graph for each column. I want to save each plot as a separate object. When I run my loop (code below) and print the graphs, all the graphs are correct. However, when I change the print() command with assign(), the graphs are not correct. The titles are changing as they should, however the graph-values are all identical (they are all the values for the final graph). I found this out because when I used plot_grid() to generate a figure of 10 plots, the graph titles and axis labels were all correct, but the values were identical!

My data set is large, so I have provided a small data set for illustration below.

Sample datafame:

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

Plots:

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)

I am thinking that when ggplots make the plot, it only renders the data from the final value of i? Or somthing like that? Is there a way around this?

I wish to do it like this, as there are a lot of graphs I wish to make and then I want to mix and match plots for figures.

Thanks!

解决方案

There are two standard ways to deal with this problem:

1- Work with a long-format data.frame

2- Use aes_string to refer to variable names in the wide format data.frame

Here's an illustration of possible strategies.

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)

Sometimes, when wrapping a ggplot call inside a function/for loop one faces issues with local variables (not the case here, if aes_string is used). In such cases one can define a local environment.

Note that using a construct like aes(y=df[,i]) may appear to work, but can produce very wrong results. Consider a facetted plot, the data.frame will be split into different groups for each panel, and this subsetting can fail miserably to group the right data if numeric values are passed directly to aes() instead of variable names.

这篇关于与ggplots循环产生具有相同的值,但标题不同的图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆