У меня есть фрейм данных, который я хотел бы преобразовать во вложенный список по строкам. Однако мне нужно сгруппировать несколько столбцов в отдельные матрицы в каждом вложенном элементе. Все решения, которые я видел, помещали каждый столбец в уникальный элемент. Я хочу создать отдельные матрицы, используя значения столбцов.
Например, если у меня есть фрейм данных, как показано ниже:
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))))
Используя 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))))