Generate a list of lists from a list of dates

Viewed 71

I am trying to go from a list of dates

dates_list = list(c(date1,date2,dateN))

to a list of lists

transformed_dates_list = list(list(date1, list(c(date1, date2)), list(c(date1, date2, dateN)))

Here is some reproducible code at my attempt

dates_list = seq_monthly(as.Date("2020-01-31"), 12)

transform_list = function(dates_list){
  
  x = list()
  
  for(i in seq_along(dates_list)){
    x[i] = dates_list[1:i]
  }
  
  return(x)
}

temp = transform_list(dates_list)

This turns the dates into numbers and does not keep the nested list structure. I tried changing the vector elements into characters but that also did not fix the nested list structure issue.

Thank you in advance for your help!

Edit: I'm sorry I forgot to include the seq monthly function I was using. However, both answers below do this more efficiently.

require(lubridate)

seq_monthly = function(from,length.out) {
  return(from %m+% months(c(0:(length.out-1))))
}

2 Answers

Since it's always the "first n elements" for each sub-list, we can iterate over a sequence counting from 1 to n, and then take the head of the vector.

dates_list = seq(as.Date("2020-01-31"), length.out = 4, by = "month")
dates_list
# [1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01"
lapply(seq_along(dates_list), head, x = dates_list)
# [[1]]
# [1] "2020-01-31"
# [[2]]
# [1] "2020-01-31" "2020-03-02"
# [[3]]
# [1] "2020-01-31" "2020-03-02" "2020-03-31"
# [[4]]
# [1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01"

We can use lapply to loop over the sequence of 'dates_list' and subset the elements from 1 to that index

lapply(seq_along(dates_list), function(i) dates_list[1:i])
#[[1]]
#[1] "2020-01-31"

#[[2]]
#[1] "2020-01-31" "2020-03-02"

#[[3]]
#[1] "2020-01-31" "2020-03-02" "2020-03-31"

#[[4]]
#[1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01"

#[[5]]
#[1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01" "2020-05-31"

# ...

Or with split

i1 <- sequence(seq_along(dates_list))
split(dates_list[i1], cumsum(i1 == 1))

In the OP's function, it needs the assignment on the [[ instead of [

transform_list <- function(dates_list){
  
  x = vector('list', length(dates_list))
  
  for(i in seq_along(dates_list)){
    x[[i]] = dates_list[1:i]
  }
  
  return(x)
}

temp <- transform_list(dates_list)
head(temp, 4)
#[[1]]
#[1] "2020-01-31"

#[[2]]
#[1] "2020-01-31" "2020-03-02"

#[[3]]
#[1] "2020-01-31" "2020-03-02" "2020-03-31"

#[[4]]
#[1] "2020-01-31" "2020-03-02" "2020-03-31" "2020-05-01"

data

dates_list = seq(as.Date("2020-01-31"), length.out = 12, by = 'month')
Related