rggplot2graph

How can I facet_wrap values of two lists?


I have two lists of vectors, one for semitones of 188 melodies and one for the timeline of each melody in seconds. I would like to use ggplot to create a graph for each melody to see the movement of said melodies over time. I feel like this should be a very easy problem to fix, especially since I can see with using plot() that single values work perfectly fine. I just can't wrap my head around how the dataframe/tibble should be organized.

As you might be able to tell, I'm not a very experienced user yet, so I hope you don't mind the possibly amateurish question. If anyone could help me, it would be very appreciated!

library(lubridate)

melodylist<-list(c(11L, 4L, 11L, 12L, 11L, 7L, 9L, 11L, NA, 11L, 12L, 14L, 12L, 
9L, 7L, 5L, 4L, 11L, 4L, 11L, 12L, 11L, 7L, 9L, 11L, NA, 11L, 
12L, 14L, 12L, 9L, 7L, 5L, 4L, NA, 9L, 7L, 12L, 11L, 9L, 14L, 
12L, 11L, 9L, NA, 12L, 11L, 12L, 14L, 7L, 11L, 12L, 9L, 7L, NA, 
7L, 12L, 11L, 9L, 4L, 7L, 5L, 4L),
c(9L, 7L, 9L, 12L, 14L, 12L, 11L, 9L, NA, 9L, 5L, 7L, 9L, 7L, 
5L, 4L, 2L, 9L, 7L, 9L, 12L, 14L, 12L, 11L, 9L, NA, 9L, 5L, 7L, 
9L, 7L, 5L, 4L, 2L, NA, 2L, 5L, 7L, 5L, 7L, 9L, NA, 9L, 14L, 
12L, 14L, 16L, 12L, 11L, 9L, NA, 9L, 12L, 9L, 12L, 7L, 5L, 2L, 
4L, 2L, 9L, 7L, 5L, 4L, 2L))

timelist<-list(new("Period", .Data = c(0, 2, 3, 4, 5, 6, 7, 8, 9, 9.5, 10, 11, 
12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 26.5, 
27, 28, 29, 30, 31, 32, 33, 34, 34.5, 35, 36, 37, 38, 38.5, 39.5, 
40, 41, 42, 42.5, 43, 44, 45, 46, 47, 47.5, 48, 49, 50, 50.5, 
51, 52, 53, 54, 55, 56, 57), year = c(0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), month = c(0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), day = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 
    hour = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0), minute = c(0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)),
new("Period", .Data = c(0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 14.5, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
29, 30, 31, 32, 32.5, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 
43.5, 44, 45, 46, 47, 48, 49, 50, 51, 51.5, 52.5, 53.5, 54.5, 
55.5, 56.5, 57, 57.5, 58.5, 59.5, 0.5, 1, 1.5, 2.5), year = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0), month = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0), day = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), hour = c(0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), minute = c(0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 
1)))

You don't have to really worry about the NAs, I'm originally using the humdrum-format which outputs them as "." and that seems to be working fine with graphing this out.

I tried to put the lists into one dataframe out of desperation, but as expected, ggplot does not play along with lists as a dataframe-entry.


Solution

  • This is a matter of data manipulation, since plotting will be easier if you convert to a single data frame.

    Essentially, you need to take each member of the melody list, pair it up with the equivalent member of the time list and create a data frame from them. You then bind the data frames together into a single data frame. We can do this with Map and rbind:

    library(lubridate)
    library(ggplot2)
    
    combined_data <- do.call("rbind",
      Map(function(m, t, g) {
        data.frame(time = as.numeric(t), melody = m, group = g)
        }, m = melodylist, t = timelist, g = c("A", "B"))
    ) 
    
    head(combined_data)
    #>   time melody group
    #> 1    0     11     A
    #> 2    2      4     A
    #> 3    3     11     A
    #> 4    4     12     A
    #> 5    5     11     A
    #> 6    6      7     A
    

    Note that I have added a group column when creating each of the data frames so that when they are stuck together we can keep track which tune we are dealing with.

    Now the plotting code is pretty simple:

    ggplot(combined_data, aes(time, melody)) +
      geom_point() +
      facet_grid(group~.) +
      theme_bw(16) 
    

    enter image description here