Nico
Nico

Reputation: 506

How to ggplot Lists of Lists

I have a list of lists. This is an example of how the list looks.

    [[7]][[8]]
           Prtf_Return Quantile       Date
2002-07-31 -0.08161658        8 2002-07-31
2003-07-31  0.05648458        8 2003-07-31
2004-07-30  0.24751328        8 2004-07-30
2005-07-29  0.26955881        8 2005-07-29
2006-07-31  0.08099889        8 2006-07-31
2007-07-31  0.14633871        8 2007-07-31
2008-07-31 -0.02790529        8 2008-07-31
2009-07-31 -0.17913224        8 2009-07-31
2010-07-30  0.33681922        8 2010-07-30
2011-07-29  0.23411797        8 2011-07-29
2012-07-31  0.10671685        8 2012-07-31
2013-07-31  0.19845169        8 2013-07-31
2014-07-31  0.11399025        8 2014-07-31
2015-07-31  0.10308543        8 2015-07-31
2016-07-29  0.01388617        8 2016-07-29
2017-07-31  0.03685517        8 2017-07-31
2018-07-31  0.09661410        8 2018-07-31

[[7]][[9]]
           Prtf_Return Quantile       Date
2002-07-31 -0.02322572        9 2002-07-31
2003-07-31  0.25252339        9 2003-07-31
2004-07-30  0.26290503        9 2004-07-30
2005-07-29  0.26407951        9 2005-07-29
2006-07-31  0.03501359        9 2006-07-31
2007-07-31  0.13907544        9 2007-07-31
2008-07-31 -0.02064978        9 2008-07-31
2009-07-31 -0.27060352        9 2009-07-31
2010-07-30  0.33156794        9 2010-07-30
2011-07-29  0.22488091        9 2011-07-29
2012-07-31  0.03268992        9 2012-07-31
2013-07-31  0.29199203        9 2013-07-31
2014-07-31  0.10818639        9 2014-07-31
2015-07-31  0.19940041        9 2015-07-31
2016-07-29  0.04085818        9 2016-07-29
2017-07-31  0.04345668        9 2017-07-31
2018-07-31  0.11842907        9 2018-07-31

The first part of the list indicates the start month, the second part the quantile ([["Start_month"]][["Quantile"]]).

The question is how can I plot the Prtf_Returns in a ggplot for every single dataframe in the list?. The following is what I got so far:

library(ggplot2)
p <- ggplot()
for(i in 1:10){
  p <- p + geom_line(data = first_year[[1]][[i]], aes(x = Date, y = cumsum(Prtf_Return), group = Quantile, colour = Quantile)) +
    scale_color_discrete(name = "Quantile", labels = rep(as.character(1:10)))
}

This is how the plot looks

What I know so far is that the legend possibly doesn't match the lines itself, but I really don't know how I could change the code to work.

Thanks in advance

Upvotes: 1

Views: 275

Answers (2)

Nico
Nico

Reputation: 506

I figured it out. Thanks to everybody that helped. The trick was to (like Rui mentioned) create a new column with the cumsums.

first_year_cumsum <- lapply(first_year, function(a) lapply(a, function(b) ddply(b, .(Quantile), transform, cumsum = cumsum(Prtf_Return))))

With that, the function of Rui looks like:

plotFun <- function(DF){
  DF[["Quantile"]] <- factor(DF[["Quantile"]])
  ggplot(data = DF, aes(x = Date, y = cumsum,
                        group = Quantile, colour = Quantile)) +
    geom_line() +
    theme_bw() +
    rotate_x_text(angle = 45) +
    scale_color_discrete(name = "Quantile", 
                         labels = as.character(1:10))
}

first_year_rbind <- lapply(first_year_cumsum, function(L) do.call(rbind, L))

p_list <- lapply(first_year_rbind, plotFun)

After that the plot returns a nice cumsum for each quantile
CumsumPlot

Thanks again

Upvotes: 0

Rui Barradas
Rui Barradas

Reputation: 76450

The trick is to rbind each of the Quantile dataframes in the sublists. Then call a plot function in a lapply loop. The plot function could be an anonymous function but I have written it separately for the sake of clarity.
I also rotate the x axis labels. To do that function rotate_x_text from package ggpubr is used.

library(ggplot2)
library(ggpubr)

plotFun <- function(DF){
  DF[["Quantile"]] <- factor(DF[["Quantile"]])
  ggplot(data = DF, aes(x = Date, y = cumsum(Prtf_Return),
                        group = Quantile, colour = Quantile)) +
    geom_line() +
    rotate_x_text(angle = 45) +
    scale_color_discrete(name = "Quantile", 
                         labels = as.character(1:10))
}

first_year_rbind <- lapply(first_year, function(L) do.call(rbind, L))

p_list <- lapply(first_year_rbind, plotFun)

p_list[[1]]

enter image description here

Test data.
This list of lists repeats the two dataframes in the question.

df1 <-
structure(list(Prtf_Return = c(-0.08161658, 0.05648458, 0.24751328, 
0.26955881, 0.08099889, 0.14633871, -0.02790529, -0.17913224, 
0.33681922, 0.23411797, 0.10671685, 0.19845169, 0.11399025, 0.10308543, 
0.01388617, 0.03685517, 0.0966141), Quantile = c(8L, 8L, 8L, 
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L), 
Date = structure(1:17, .Label = c("2002-07-31", 
"2003-07-31", "2004-07-30", "2005-07-29", "2006-07-31", "2007-07-31", 
"2008-07-31", "2009-07-31", "2010-07-30", "2011-07-29", "2012-07-31", 
"2013-07-31", "2014-07-31", "2015-07-31", "2016-07-29", "2017-07-31", 
"2018-07-31"), class = "factor")), class = "data.frame", 
row.names = c("2002-07-31", 
"2003-07-31", "2004-07-30", "2005-07-29", "2006-07-31", "2007-07-31", 
"2008-07-31", "2009-07-31", "2010-07-30", "2011-07-29", "2012-07-31", 
"2013-07-31", "2014-07-31", "2015-07-31", "2016-07-29", "2017-07-31", 
"2018-07-31"))

df2 <-
structure(list(Prtf_Return = c(-0.02322572, 0.25252339, 0.26290503, 
0.26407951, 0.03501359, 0.13907544, -0.02064978, -0.27060352, 
0.33156794, 0.22488091, 0.03268992, 0.29199203, 0.10818639, 0.19940041, 
0.04085818, 0.04345668, 0.11842907), Quantile = c(9L, 9L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L), 
Date = structure(1:17, .Label = c("2002-07-31", 
"2003-07-31", "2004-07-30", "2005-07-29", "2006-07-31", "2007-07-31", 
"2008-07-31", "2009-07-31", "2010-07-30", "2011-07-29", "2012-07-31", 
"2013-07-31", "2014-07-31", "2015-07-31", "2016-07-29", "2017-07-31", 
"2018-07-31"), class = "factor")), class = "data.frame", 
row.names = c("2002-07-31", 
"2003-07-31", "2004-07-30", "2005-07-29", "2006-07-31", "2007-07-31", 
"2008-07-31", "2009-07-31", "2010-07-30", "2011-07-29", "2012-07-31", 
"2013-07-31", "2014-07-31", "2015-07-31", "2016-07-29", "2017-07-31", 
"2018-07-31"))

first_year <- list(list(df1, df2), list(df1, df2))

Upvotes: 1

Related Questions