1
votes

Suppose I have a dataframe with 10 rows and 5 columns like this

df <- data.frame(matrix(rep(1:10, 5), ncol=5))

I want to split the dataframe into a list with 5 vectors of unequal length, where first vector begins with the first row of column one, second vector begins with the second row of column two, and so on. I will provide the index where each of the vectors shall end. For example, if this index vector is c(3, 5, 4, 8, 10) then I expect the list to be list(1:3, 2:5, 3:4, 4:8, 5:10). Thanks!

3
I am amazed how fast people response and how great the answers are. That literally saved me hours. All of them answer my question so I upvoted them but can't choose one over the other. Thanks so much!machine
I understand the quandary, though choosing one over the other is partially for the answerer and partially for the community: it marks the question as resolved.r2evans
@r2evans alright, I chosed one. Thanks.machine

3 Answers

4
votes
Map(function(x, a, b) x[a:b], df, seq_along(df), c(3, 5, 4, 8, 10))
# $X1
# [1] 1 2 3
# $X2
# [1] 2 3 4 5
# $X3
# [1] 3 4
# $X4
# [1] 4 5 6 7 8
# $X5
# [1]  5  6  7  8  9 10
2
votes

An option is imap which by default have sequence as the .y when the vector of list is unnamed

library(purrr)
imap(v1, ~ .y:.x)
#[[1]]
#[1] 1 2 3

#[[2]]
#[1] 2 3 4 5

#[[3]]
#[1] 3 4

#[[4]]
#[1] 4 5 6 7 8

#[[5]]
#[1]  5  6  7  8  9 10

data

v1 <- c(3, 5, 4, 8, 10)
1
votes
x = c(3, 5, 4, 8, 10)
lapply(seq_along(x), function(i) df[cbind(i:x[i], i)])
#[[1]]
#[1] 1 2 3

#[[2]]
#[1] 2 3 4 5

#[[3]]
#[1] 3 4

#[[4]]
#[1] 4 5 6 7 8

#[[5]]
#[1]  5  6  7  8  9 10

OR

x = c(3, 5, 4, 8, 10)
i = rep(seq_along(x), x - seq_along(x) + 1)
split(df[cbind(i + sequence(rle(i)$lengths) - 1, i)], names(df)[i])
#$X1
#[1] 1 2 3

#$X2
#[1] 2 3 4 5

#$X3
#[1] 3 4

#$X4
#[1] 4 5 6 7 8

#$X5
#[1]  5  6  7  8  9 10