2

I am kind of stuck with the for loop in ggplot2.

I am trying to adding Species and categ names to each plot title as well as the file name through the for loop in ggplot2. Somehow, the loop seems to taking only one Species name to title.

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

PLOT PART

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()
}
}

ant the output is like this (I didn't add all plots and names. But you will see them in working directory)

enter image description here

So, as we can see the problem is here I can't get the correct Species name for each plot. I could not get it? Why this is happening ?

4
  • 1
    In plot_list[[j]] you don't account for i, so you're only going to end up with plots for one value of i, the previous plots will be overwritten. You also don't filter the data based on i at all in your plotting loop, I'm not sure what you were hoping to do with that. Commented May 17, 2018 at 1:00
  • @Marius You mean I should put the filter for Species for too ? How? Commented May 17, 2018 at 1:01
  • I can't really answer that as I don't know exactly what you were aiming to achieve - you may not need the for (i in unique(data_iris$Species)) outer loop at all if you don't actually need to change the data within the loop based on i. Commented May 17, 2018 at 1:21
  • @Marius What I want to achieve in finally is that, For each Species plot subcategory of categ and put Species and categ names in the title as well as in the output file. Is this clear ? Commented May 17, 2018 at 1:24

3 Answers 3

3

Try this. Your indexing is wrong. I would probably store the plots differently in the first place - maybe in a list of lists.

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_A_iris_plot__

setosa_B_iris_plot__ setosa_B_iris_plot__

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much. This is the solution I was looking for:) I really appreciated it!
Cheers. Still think using a list of list is probably a better approach.
1

A solution using purrr::map, walk & iwalk in the tidyverse framework

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"))
     )

Created on 2018-05-16 by the reprex package (v0.2.0).

1 Comment

Thank you for your solution. Another horizon for me to reach:)
1

I figured out just adding Species_categ column and run it through the loop is seems to be less complex.

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()
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.