Search code examples
rggplot2dplyrapply

Repeat a ggplot for each value of a variable in the dataframe


I want to make a graph for each value of a variable in my dataframe, and then pass that value through to the graph as the title. I think the best way to do this is by using the apply() family of functions, but i'm a bit of a novice and can't figure out how to do that.

For example, say I have this dataframe:

df <- data.frame(furniture = c("Chair", "Table", "Rug", "Wardrobe", "Chair", "Desk", "Lamp", "Shelves", "Curtains", "Bed"),
                 cutlery = c("Fork", "Knife", "Spatula", "Spoon", "Corkscrew", "Fork", "Tongs", "Chopsticks", "Spoon", "Knife"),
                 type = c("bbb", "ccc", "aaa", "bbb", "ccc", "aaa", "bbb", "ccc", "aaa", "bbb"),
                 count = c(341, 527, 2674, 811, 1045, 4417, 1178, 1192, 4793, 916))

I could manually go through and select on the value of type doing this:

df %>% 
  filter(type=='aaa') %>% 
  ggplot() +
  geom_col(aes(furniture, count)) +
  labs(title = 'value of {{type}} being plotted')

df %>% 
  filter(type=='bbb') %>% 
  ggplot() +
  geom_col(aes(furniture, count)) +
  labs(title = 'value of {{type}} being plotted')

df %>% 
  filter(type=='ccc') %>% 
  ggplot() +
  geom_col(aes(furniture, count)) +
  labs(title = 'value of {{type}} being plotted')

But this quickly becomes a lot of code, with enough levels of type and assuming a fair amount of additional code for each plot. Let's also assume that I don't want to use facet_wrap(~type). As you can see, the values of the x variable vary quite a lot across values of type so facet_wrap() results in lots of missing spaces along the x-axis. Ideally i'd just create a function that takes as an input the x and y variables, and type and then filters on type, makes the plot, and extracts the value of type to use in the title.

Can anyone help me out with this?


Solution

  • Or you can create your custom function and then lapply over the levels of type

    myplot <- function(var){
      df %>% 
        filter(type==var) %>% 
        ggplot() +
        geom_col(aes(month, count)) +
        labs(title = paste0("value of ",var))
    }
    plot.list <- lapply(unique(df$type), myplot)
    plot.list[[1]]
    plot.list[[2]]
    plot.list[[3]]
    

    EDIT

    to include the x variable as argument::

    myplot <-
      function(var, xvar) {
        df %>%   
          filter(type == var) %>%   
          ggplot() + 
          geom_col(aes(x={{xvar}}, count)) +   
          labs(title = paste0("value of ", var))
      }
    
    plot.list <- lapply(unique(df$type), myplot,xvar=cutlery)
    

    you miss the {{}} (aka 'curly curly') operator that replaces the approach of quoting with enquo and unquoting with !! (aka 'bang-bang'), and the argument xvar has to be passed as an extra argument of lapply and not of the function inside lapply