Создайте вложенный список из фрейма данных, используя несколько столбцов

У меня есть фрейм данных, который я хотел бы преобразовать во вложенный список по строкам. Однако мне нужно сгруппировать несколько столбцов в отдельные матрицы в каждом вложенном элементе. Все решения, которые я видел, помещали каждый столбец в уникальный элемент. Я хочу создать отдельные матрицы, используя значения столбцов.

Например, если у меня есть фрейм данных, как показано ниже:

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

Я хотел бы преобразовать его во что-то вроде этого:

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
55
3

Ответы:

Решено

Используя purrr:

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

В базе R вы можете split, а затем создать свой список для каждого, используя 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))]

Или все в одной строке, благодаря замечательному совету @Friede:

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

Оба подхода дают результат:

# $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   

Для каждой строки создайте список матриц в новом столбце data, а затем извлеките этот столбец. Обратите внимание, что в вопросе входные данные целочисленные, но dflist содержит двойные значения. Мы предполагаем, что это не было задумано, и вместо этого используем dflist, как определено в примечании в конце.

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

Примечание

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))))