【问题标题】:Saving graphs with for loop in ggplot2在ggplot2中使用for循环保存图形
【发布时间】:2018-05-17 00:54:08
【问题描述】:

我有点卡在ggplot2 中的for loop

我正在尝试通过 ggplot2 中的 for 循环将 Speciescateg 名称添加到每个绘图标题以及文件名。不知何故,这个循环似乎只取了一个物种名称作为标题。

library(dplyr)
data_iris <- iris%>%
  mutate(categ=ifelse(Petal.Width<0.4,"A",ifelse(Petal.Width>=0.4&Petal.Width<=1.0, "B","C")))

> head(data_iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species categ
1          5.1         3.5          1.4         0.2  setosa     A
2          4.9         3.0          1.4         0.2  setosa     A
3          4.7         3.2          1.3         0.2  setosa     A
4          4.6         3.1          1.5         0.2  setosa     A
5          5.0         3.6          1.4         0.2  setosa     A
6          5.4         3.9          1.7         0.4  setosa     B

剧情部分

for (i in unique(data_iris$Species)) {

for (j in unique(data_iris$categ)) {

  p = ggplot(data_iris[data_iris$categ==j,], aes(x=Sepal.Length, y=Sepal.Width)) +
    geom_point(size=3, aes(colour=categ))+

    labs(title=paste( i,j, "species_categ",sep="_")) #this part is not working!!!

  plot_list[[j]] = p
}
}  

# Save plots to tiff. Makes a separate file for each plot.


library(ggplot2)

for (i in unique(data_iris$Species)) {

for (j in unique(data_iris$categ)) {
  file_name = paste(i,j, "iris_plot_", ".tiff", sep="_")
  tiff(file_name)
  print(plot_list[[j]])
  dev.off()
}
}

输出是这样的(我没有添加所有的图和名称。但是你会在工作目录中看到它们)

所以,正如我们所见,问题出在此处,我无法为每个地块获得正确的 Species 名称。我无法得到它?为什么会这样?

【问题讨论】:

  • plot_list[[j]] 中,您没有考虑i,因此您最终只会得到一个值为i 的图,之前的图将被覆盖。您也根本没有在绘图循环中根据 i 过滤数据,我不确定您希望用它做什么。
  • @Marius 你的意思是我也应该为Species 设置过滤器?怎么样?
  • 我无法真正回答这个问题,因为我不知道您的目标是什么 - 如果您实际上不需要更改,您可能根本不需要 for (i in unique(data_iris$Species)) 外循环循环内的数据基于i
  • @Marius 我最终想要实现的是,对于每个Species 绘制categ 的子类别,并将Speciescateg 名称放在标题和输出中文件。这清楚吗?

标签: r for-loop ggplot2


【解决方案1】:

试试这个。 你的索引是错误的。我可能会首先以不同的方式存储图 - 可能在列表列表中。

ind <- 1 # initialise the index for storing

for (i in unique(data_iris$Species)) {
  for (j in unique(data_iris$categ)) {

    p <- ggplot(data_iris[data_iris$categ==j,], aes(x=Sepal.Length, y=Sepal.Width)) +
      geom_point(size=3, aes(colour=categ))+

      labs(title=paste( i,j, "species_categ",sep="_")) 

    plot_list[[ind]] <- p  # stor the plot
    ind <- ind + 1         # increment   
  }
}  

ind <- 1
for (i in unique(data_iris$Species)) {
  for (j in unique(data_iris$categ)) {

    file_name = paste(i,j, "iris_plot_", ".tiff", sep="_")
    tiff(file_name)
    print(plot_list[[ind]]) # use the same index to retrieve the plot
    ind <- ind + 1
    dev.off()
  }
}

setosa_A_iris_plot__

setosa_B_iris_plot__

【讨论】:

  • 非常感谢。这是我一直在寻找的解决方案:)我真的很感激!
  • 干杯。仍然认为使用列表列表可能是更好的方法。
【解决方案2】:

tidyverse 框架中使用purrr::map, walk &amp; iwalk 的解决方案

library(tidyverse)

data_iris <- iris%>%
  as_tibble() %>% 
  mutate(categ = ifelse(Petal.Width < 0.4, "A",
                        ifelse(Petal.Width >= 0.4 & Petal.Width <= 1.0, "B", "C")))
data_iris

#> # A tibble: 150 x 6
#>    Sepal.Length Sepal.Width Petal.Length Petal.Width Species categ
#>           <dbl>       <dbl>        <dbl>       <dbl> <fct>   <chr>
#>  1          5.1         3.5          1.4         0.2 setosa  A    
#>  2          4.9         3            1.4         0.2 setosa  A    
#>  3          4.7         3.2          1.3         0.2 setosa  A    
#>  4          4.6         3.1          1.5         0.2 setosa  A    
#>  5          5           3.6          1.4         0.2 setosa  A    
#>  6          5.4         3.9          1.7         0.4 setosa  B    
#>  7          4.6         3.4          1.4         0.3 setosa  A    
#>  8          5           3.4          1.5         0.2 setosa  A    
#>  9          4.4         2.9          1.4         0.2 setosa  A    
#> 10          4.9         3.1          1.5         0.1 setosa  A    
#> # ... with 140 more rows

# Split based on species and categories
# Remove lists having 0 row
data_iris %>% 
  split(list(.$Species, .$categ)) %>% 
  discard(function(x) nrow(x) == 0) -> df_split

# For all species and categories
plots <- map(df_split,  
             ~ ggplot(.x, aes(x = Sepal.Length, y = Sepal.Width)) +
               geom_point(size = 3, aes(colour = categ))+
               theme_bw(base_size = 16) +
               labs(title = paste0("Species: ", .x$Species, " | Category: ", .x$categ)))

# Check the 1st plot
plots[[1]]

# Display all plots using purrr::walk
walk(plots, print) 

# Save all plots using purrr::iwalk
iwalk(plots,  
     ~ ggsave(plot = .x,
              filename = paste0("./img/", .y, ".tiff"))
     )

reprex package (v0.2.0) 于 2018 年 5 月 16 日创建。

【讨论】:

  • 感谢您的解决方案。我要到达的另一个地平线:)
【解决方案3】:

我发现只需添加 Species_categ 列并通过循环运行它似乎不那么复杂。

data_iris <- iris%>%
  mutate(categ=ifelse(Petal.Width<0.4,"A",ifelse(Petal.Width>=0.4&Petal.Width<=1.0, "B","C")))%>%
  unite(Species_categ,Species,categ,remove=F) #added this line

plot_list = list()

for (i in unique(data_iris$Species_categ)) {

  p = ggplot(data_iris[data_iris$Species_categ==i,], aes(x=Sepal.Length, y=Sepal.Width)) +
    geom_point(size=3, aes(colour=categ))+

    labs(title=paste( i, "species_categ",sep="_"))

  plot_list[[i]] = p
}


    # Save plots to tiff. Makes a separate file for each plot.
    for (i in unique(data_iris$Species_categ)) {

      file_name = paste(i, "iris_plot_2", ".tiff", sep="_")
      tiff(file_name)
      print(plot_list[[i]])
      dev.off()
    }

【讨论】:

    猜你喜欢
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多