Jeff Henderson
Jeff Henderson

Reputation: 683

Map write multiple ggplot png files using Purrrr

I'm trying to use the purrr map function to efficiently write many ggplot images through one call. I wrote example code that's simple for example sake. The approach I took below results in empty png files. It will write and I can open the file but it's all blank. I'm guessing something wrong in the paste0 call? Maybe there's a better way to automate the file name.

structure(list(Sepal.Length = c(5.8, 5.7, 5.7, 7, 6.9, 6.8, 7.7, 
7.7, 7.7, 7.9, 7.7), Sepal.Width = c(4, 4.4, 3.8, 3.2, 3.1, 2.8, 
3.8, 2.6, 2.8, 3.8, 3), Petal.Length = c(1.2, 1.5, 1.7, 4.7, 
4.9, 4.8, 6.7, 6.9, 6.7, 6.4, 6.1), Petal.Width = c(0.2, 0.4, 
0.3, 1.4, 1.5, 1.4, 2.2, 2.3, 2, 2, 2.3), Species = structure(c(1L, 
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), levels = c("setosa", 
"versicolor", "virginica"), class = "factor")), class = 
c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -11L), groups = 
structure(list(
Species = structure(1:3, levels = c("setosa", "versicolor", 
"virginica"), class = "factor"), .rows = structure(list(1:3, 
    4:6, 7:11), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, -3L), class = 
c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE))

library(gapminder)

df <- dput(iris %>% 
  group_by(Species) %>% 
  top_n(3, wt = Sepal.Length))


map(.x = c("setosa", "veriscolor", "virginica"),
.f = function(x) {
  foo <- df %>% 
    filter(Sepal.Length == x) %>% 
    ggplot(aes(Sepal.Length))+
    geom_histogram()
  
  Cairo(width = 1300, height = 1600, paste0(x," test.", "png"))
  print(foo)
  dev.off()
  
  
})

output [[1]] null device 1

[[2]] null device 1

[[3]] null device 1

Upvotes: 0

Views: 133

Answers (2)

jkatam
jkatam

Reputation: 3447

There are couple of updates required

  1. in filter replace the Sepal.Length == x with Species == x
  2. I dont see a function like Cairo, replace with ggsave
  3. when we use ggsave, it will save the plots to default location so check that folder
  4. changed the width and height of plots in ggsave

code

map(.x = c("setosa", "veriscolor", "virginica"),
    .f = function(x) {
      foo <- df %>% 
        filter(Species == x) %>% 
        ggplot(aes(Sepal.Length))+
        geom_histogram()
      
      ggsave(width = 14, height = 7, paste0(x," test.", "png"))
      print(foo)
      dev.off()
    })

Created on 2023-01-20 with reprex v2.0.2

check the default location with getwd() and in that location check the saved plots

Upvotes: 1

starja
starja

Reputation: 10365

Your code has several issues:

  • you filter for Sepal.Length, but you actually provide the Species names, so you have to filter for Species
  • you've had a typo in versicolor
  • if you're only interested in the side effect of a function, use walk instead of map
  • for ggplots, the preferable way to save them is ggsave
library(dplyr)
library(purrr)
library(ggplot2)

df <- iris %>% 
  group_by(Species) %>% 
  top_n(3, wt = Sepal.Length)


walk(.x = c("setosa", "versicolor", "virginica"),
     .f = function(x) {
       foo <- df %>% 
         filter(Species == x) %>% 
         ggplot(aes(Sepal.Length))+
         geom_histogram()
       
       ggsave(paste0(x," test.", "png"),
              plot = foo,
              width = 1300,
              height = 1600,
              units = "px")
       
     })

Upvotes: 0

Related Questions