Search code examples
rggplot2graphdata-sciencedata-visualization

Plot lists of time series data for factors in R


I have a series of lists describing duration (in days) of events, and I would like to plot this data as lines to compare the lists.

Below is some example data on what lunch options were served on which days at school. I have already parsed my data and this is the reduced form. Originally it was in the form of complex character strings.

soup = c(15:18)
grilledcheese = c(0:19)
pasta = c(3:13)

I want to create a graph similar to this one, with days on the x axis and soup, grilled cheese, and pasta on the y axis: enter image description here

I looked online and I'm not sure what kind of graph to use for this. Part of the difficulty is that the data does not start at 0 and the y axis should represent factors.

What I tried:

I tried plotting this in ggplot but it only takes data frames. I am wondering if there is a way to plot directly from lists. It seems like there should be a straightforward solution here that maybe I am missing.

I also tried this

plot(x = grilledcheese, y = rep(1, length(grilledcheese)))

which is closer to what I want, but I'm not sure how to plot multiple factors on the y axis.


Solution

  • First, let's get your data in a shape easier to handle with ggplot2:

    library(tidyverse)    
    soup = c(15:18)
    grilledcheese = c(0:19)
    pasta = c(3:13)
    
    
    df <- data.frame(soup_min = c(min(soup),max(soup)),
                     grilledcheese = c(min(grilledcheese),max(grilledcheese)),
                     pasta = c(min(pasta),max(pasta)))
    
    df <- pivot_longer(df, cols = 1:3) %>% 
      group_by(name) %>% 
      mutate(minv = min(value),
             maxv = max(value)) %>% 
      ungroup() %>% 
      select(-value) %>% 
      distinct()
    

    Data

    # A tibble: 3 x 3
      name           minv  maxv
      <chr>         <int> <int>
    1 soup_min         15    18
    2 grilledcheese     0    19
    3 pasta             3    13
    

    Graph

    We can then plot the different elements you want: the starting and ending dots for each line, the lines themselves and the axis theme.

    ggplot(df) +
      geom_segment(aes(x = minv, xend = maxv, y = name, yend = name)) +
      geom_point(aes(x = minv, y = name)) +
      geom_point(aes(x = maxv, y = name)) +
      scale_x_continuous(breaks = c(0:20),
                         labels = c(0:20),
                         limits = c(0,20),
                         expand = c(0,0)) +
      theme(axis.ticks.x = element_line(size = 1),
            axis.ticks.y = element_blank(),
            axis.ticks.length =unit(.25, "cm"),
            axis.line.x = element_line(size = 1),
            panel.background = element_blank()) +
      labs(x = "",
           y = "")
    

    We get this:

    First_graph

    This should do the trick.

    Extra custom

    Now, if you want to have the ticks labels in-between the ticks, you might want to check here because you will have to reshape your data, and get the graph done once you have all the food types you want. Until, I just add spacing with-in the labels :

    ggplot(df) +
      geom_segment(aes(x = minv, xend = maxv, y = name, yend = name)) +
      geom_point(aes(x = minv, y = name)) +
      geom_point(aes(x = maxv, y = name)) +
      scale_x_continuous(breaks = c(0:20),
                         labels = paste("         ",0:20),
                         limits = c(0,20),
                         expand = c(0,0)) +
      theme(axis.ticks.x = element_line(size = 1),
            axis.ticks.y = element_blank(),
            axis.ticks.length =unit(.25, "cm"),
            axis.line.x = element_line(size = 1),
            panel.background = element_blank()) +
      labs(x = "",
           y = "")
    

    Graph2