3

I have a dataframe that I would like to convert to a nested list, by row. However, I need to group several columns into separate matrices in each nested element. All of the solutions I've seen put each column into a unique element. I want to create separate matrices using the column values.

For example, if I have a dataframe as below:

df = data.frame(a=c("foo", "bar", "baz"), b=1:3, c=3:1, d=4:6, e=6:4)

I'd like to convert it to something like this:

dflist <- list(foo=list(as.matrix(c(1,3)),
                        as.matrix(c(4,6))),
               bar=list(as.matrix(c(2,2)),
                        as.matrix(c(5,5))),
               baz=list(as.matrix(c(3,1)),
                        as.matrix(c(6,4))))

3 Answers 3

2

In base R, you can split and then create your list for each using lapply:

ll <- lapply(split(df, df$a), \(x) list(matrix(x[2:3]), matrix(x[4:5])))

#If order matters (above is alphabetical (bar, bar, foo):
ll_ordered <- ll[match(df$a, names(ll))]

Or all in one line, thanks to the great advice by @Friede:

lapply(split(df, factor(f <- df$a, f)), \(x) list(matrix(x[2:3]), matrix(x[4:5])))

Both approaches give the out output:

# $foo
# $foo[[1]]
# [,1]
# [1,] 1   
# [2,] 3   
# 
# $foo[[2]]
# [,1]
# [1,] 4   
# [2,] 6   
# 
# 
# $bar
# $bar[[1]]
# [,1]
# [1,] 2   
# [2,] 2   
# 
# $bar[[2]]
# [,1]
# [1,] 5   
# [2,] 5   
# 
# 
# $baz
# $baz[[1]]
# [,1]
# [1,] 3   
# [2,] 1   
# 
# $baz[[2]]
# [,1]
# [1,] 6   
# [2,] 4   
Sign up to request clarification or add additional context in comments.

Comments

1

Using purrr:

mylist <- pmap(df, \(b, c, d, e, ...) {
  list(as.matrix(c(b, c)), as.matrix(c(d, e)))
}) |> setNames(df$a)

Comments

0

For each row create the list of matrices in a new column, data, and then extract that column. Note that in the question the input is integer but dflist contains doubles. We assume that was not intended and use dflist as defined in the Note at the end instead.

library(dplyr)

result <- df %>%
  rowwise %>%
  mutate(data = list(cbind(c(b, c)), cbind(c(d, e))) %>%
    list %>%
    setNames(a)) %>%
  pull(data)

identical(result, dflist)
## [1] TRUE

Note

dflist <- list(foo=list(as.matrix(c(1L,3L)),
                        as.matrix(c(4L,6L))),
               bar=list(as.matrix(c(2L,2L)),
                        as.matrix(c(5L,5L))),
               baz=list(as.matrix(c(3L,1L)),
                        as.matrix(c(6L,4L))))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.