Prevost
Prevost

Reputation: 697

Function to create and append ggplots to new list with names from existing list

I would like to create a named list containing plots. I create a list from a vector containing unique IDs that I use to filter a master dataframe containing all the info.

I then have a function that I use in lapply to loop through the list of unique IDs to filter the master dataframe and create the plots. I then want to append each plot to an (originally) initialized list and I would like the names of the list entry to be equal to the list value passed in lapply.

My code below creates the plots, however the appended list does not have the corresponding names of the passed list id values.

Do I have the wrong approach? I have seen questions/answer that use names(list) etc. but the list passed into lapply is not named, I want passed list entries to become the names of the new list.

Thanks in advance!

library(ggplot2)
library(dplyr)

unique_names = as.list(c("apple", "banana", "carrots"))
listy = list()
dframe = data.frame(x_var = seq(1:9)) %>% 
  mutate(y_var = x_var^3)
temp = data.frame(id = c("apple", "apple", "apple", "banana", "banana", "banana", "carrots", "carrots", "carrots"))
dframe = bind_cols(dframe,
                   temp)

fun_plots = function(my_list,
                     my_df,
                     my_appending_list) {
  a = filter(my_df,
             id == my_list)
  plt = ggplot() +
    geom_line(data = a,
              aes(x = x_var,
                  y = y_var))

  my_appending_list$my_list = plt
}

plot_list = lapply(unique_names,
                   fun_plots,
                   my_df = dframe,
                   my_appending_list = listy)

Upvotes: 0

Views: 767

Answers (3)

beigel
beigel

Reputation: 1200

You can avoid writing a function and mutating a list with a little bit more dplyr magic. If I understand correctly you want a separate plot object for each value of the "id" variable - if so you can perform a group_by on "id" and then generate a ggplot object for each set. Here's how

plot_df <- dframe %>% 
  group_by(id) %>% 
  do(plot = ggplot(.data) + geom_line(aes(x = x_var, y = y_var)) + ggtitle(.data$id))
plot_df
#> Source: local data frame [3 x 2]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 2
#>        id     plot
#> *  <fctr>   <list>
#> 1   apple <S3: gg>
#> 2  banana <S3: gg>
#> 3 carrots <S3: gg>

You can facet on the id variables to have one ggplot2. For instance:

ggplot(dframe) + geom_line(aes(x = x_var, y = y_var)) + facet_wrap(~ id)

Upvotes: 2

James Thomas Durant
James Thomas Durant

Reputation: 305

You can use dplyr group_by to accomplish this:

library(ggplot2)
library(dplyr)

unique_names = as.list(c("apple", "banana", "carrots"))
listy = list()
dframe = data.frame(x_var = seq(1:9)) %>% 
  mutate(y_var = x_var^3)
temp = data.frame(id = c("apple", "apple", "apple", "banana", "banana", "banana", "carrots", "carrots", "carrots"))
dframe = bind_cols(dframe,
                   temp)

dframe <- group_by(dframe, id) %>% do(plots=ggplot(data=.) +
                              aes(x=x_var, y=y_var) + geom_line() + ggtitle(unique(.$id)))

mylist <- as.list(dframe$plots)

mylist

HTH James

Upvotes: 0

Marius
Marius

Reputation: 60140

You can take out the my_appending_list argument as it doesn't actually achieve anything at the moment, you aren't modifying the listy object within the function. You can just do:

fun_plots = function(my_list,
                     my_df) {
    a = filter(my_df,
               id == my_list)
    plt = ggplot() +
        geom_line(data = a,
                  aes(x = x_var,
                      y = y_var))

    plt
}

plot_list = lapply(unique_names,
                   fun_plots,
                   my_df = dframe)
names(plot_list) = unique_names

Upvotes: 1

Related Questions