【问题标题】:Save ggplot in loop with R使用 R 将 ggplot 保存在循环中
【发布时间】:2019-01-15 17:31:14
【问题描述】:

我有一个包含数值变量和因子变量的数据集。我想用数字做一页,用因子 var 做一页。首先,我用他的索引选择factor var。

我的 df 是 IRIS 数据集。

df<-iris
df$y<-sample(0:1,nrow(iris),replace=TRUE)
fact<-colnames(df)[sapply(df,is.factor)]
index_fact<-which(names(df)%in%fact)

然后我计算其余部分(数字)

nm<-ncol(df)-length(fact)

下一步是创建循环

i_F=1
i_N=1
list_plotN<- list()
list_plotF<- list()

for (i in 1:length(df)){
  plot <- ggplot(df,aes(x=df[,i],color=y,fill=y))+xlab(names(df)[i]) 

  if (is.factor(df[,i])){
    p_factor<-plot+geom_bar()
    list_plotF[[i_F]]<-p_factor
    i_F=i_F+1
  }else{
    p_numeric <- plot+geom_histogram()
    list_plotN[[i_N]]<-p_numeric
    i_N=i_N+1
  }
}

当我看到 list_plotF 和 list_plot_N 时,它并不好。它总是有相同的变量。我不知道我做错了什么。

谢谢!!!

【问题讨论】:

标签: r loops ggplot2


【解决方案1】:

我并没有很好地遵循您的 for 循环代码。但据我所知,它似乎在保存你制作的每个循环中的最后一个情节。我已经重建了我认为你需要使用 lapply 的东西。我通常更喜欢 lapply 而不是 for 循环。

Lapply 获取一个值列表和一个函数,并将该函数应用于每个值。你可以像我一样单独定义你的函数,所以一切看起来更干净。然后你就在 lapply 命令中提到这个函数。

在我们的例子中,列表是您的数据框df 中的列列表。它首先应用的函数创建了我们的基本图。然后它会快速检查它正在查看的列是否是一个因素。如果它是一个因素,它会创建一个条形图,否则它会创建一个直方图。

histOrBar <- function(var) {
  basePlot <- ggplot(df, aes_string(var))
  if ( is.factor(df[[var]]) ) {
    basePlot + geom_bar()  
  } else {
    basePlot + geom_histogram()
  }
}

loDFs <- lapply(colnames(df), histOrBar)

【讨论】:

  • 是否有可能传递 df 之类的 apply 参数? @Sahir Moosvi
  • 有一组应用函数。基本的应用函数可以接受一个数据框。
【解决方案2】:

考虑使用aes_string 传递列名以更好地将xdf 对齐:

for (i in 1:length(df)){
    plot <- ggplot(df, aes_string(x=names(df)[i], color="y", fill="y")) + 
              xlab(names(df)[i]) 
    ...
}

为了演示在 OP 上下文中使用 aes() 的问题和使用 aes_string() 的解决方案,请考虑以下具有不同数据类型列的随机数据框:factor、char、int、num、bool、date。

数据

library(ggplot2)

set.seed(1152019)
alpha <- c(LETTERS, letters, c(0:9))
data_tools <- c("sas", "stata", "spss", "python", "r", "julia")

random_df <- data.frame(
  group = sample(data_tools, 500, replace=TRUE),
  int = as.numeric(sample(1:15, 500, replace=TRUE)),
  num = rnorm(500),
  char = replicate(500, paste(sample(LETTERS[1:2], 3, replace=TRUE), collapse="")),
  bool = as.numeric(sample(c(TRUE, FALSE), 500, replace=TRUE)),
  date = as.Date(sample(as.integer(as.Date('2019-01-01', origin='1970-01-01')):as.integer(Sys.Date()), 
                        500, replace=TRUE), origin='1970-01-01')
)

图表

fact <- colnames(random_df)[sapply(random_df,is.factor)]
index_fact <- which(names(random_df) %in% fact)

i_F=1
i_N=1
list_plotN <- list()
list_plotF <- list()
plot <- NULL

for (i in 1:length(random_df)){
  # aes() VERSION
  #plot <- ggplot(random_df, aes(x=random_df[,i], color=group, fill=group)) +
  #  xlab(names(random_df)[i]) 

  # aes_string() VERSION
  plot <- ggplot(random_df, aes_string(x=names(random_df)[i], color="group", fill="group")) +
    xlab(names(random_df)[i]) 

  if (is.factor(random_df[,i])){
    p_factor <- plot + geom_bar()
    list_plotF[[i_F]] <- p_factor
    i_F=i_F+1
  }else{
    p_numeric <- plot + geom_histogram()
    list_plotN[[i_N]] <- p_numeric
    i_N=i_N+1
  }
}

问题 (使用aes(),其中图形输出不会根据类型而变化)


解决方案 (使用aes_string(),其中图表会根据类型而变化)

【讨论】:

  • 真的吗?你得到什么错误?对我来说效果很好。
  • 仔细想想,你的问题不清楚。 它总是有相同的变量。 ...这是什么意思?如果没有aes_string,x 轴不会在我认为是您的 same vars 问题的图之间发生变化。
  • 如果您看到 list_plotF(因子变量的预期图形)和 list_plotN(预期图形数字变量),您可以检查两个列表是否相同。 even plot 是一个包含所有地块的列表。
  • 我编辑显示在您的上下文中使用 aes()aes_string() 的差异。我相信iris 可能不是一个很好的例子,因为除了 species 之外的所有列都是数字的。查看我的所有类型列的随机数据(为可重复性播种):char、num、int、bool 和 date。查看问题和解决方案的输出。
  • 您使用的是什么 IDE?工作室?瑞吉?命令行中的Rscript?你是怎么看剧情的?
猜你喜欢
  • 2022-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-17
相关资源
最近更新 更多