通过分组因子对 data.frame 中的矩阵列表列求和
Sum a list column of matrices in a data.frame by grouping factor
我有一个 dataframe
,其中一列是一个列表,其中包含每一行的矩阵,为该观察定义了一个转换矩阵。
library(tidyverse)
m <- matrix(1:4, ncol = 2)
d <- data_frame(g = c('a', 'a', 'b', 'b', 'b', 'c'),
m = rep(list(m), 6))
这看起来像:
# A tibble: 6 × 2
g m
<chr> <list>
1 a <int [2 × 2]>
2 a <int [2 × 2]>
3 b <int [2 × 2]>
4 b <int [2 × 2]>
5 b <int [2 × 2]>
6 c <int [2 × 2]>
我想得到两个矩阵的列表,a
和 b
,它们是每个分组因子的所有矩阵的总和。我需要这种方法来泛化到任意数量的组,因为我不会提前知道分组因子的数量。
我试过by_slice
和do
,但我所能输出的只是所有矩阵的总和,或者a
或[=15=的总和] 单独的矩阵——不绑定在一个组中。
您可以通过将矩阵嵌套在组中(使用 tidyr 的 nest
)来实现,这会创建一个包含矩阵列表的列表列。然后,您可以使用 purrr 的 map
和 reduce
来总结每个组列表中的矩阵:
results <- d %>%
nest(-g) %>%
mutate(summed = map(data, ~ reduce(.$m, `+`)))
结果:
# A tibble: 3 × 3
g data summed
<chr> <list> <list>
1 a <tibble [2 × 1]> <int [2 × 2]>
2 b <tibble [3 × 1]> <int [2 × 2]>
3 c <tibble [1 × 1]> <int [2 × 2]>
summed
列将在每个组内添加矩阵。
如果您想将其转换为包含矩阵项 a/b/c 的命名列表,您可以这样做:
lst <- results$summed
names(lst) <- results$g
lst
或者:
results %>%
select(-data) %>%
spread(g, summed)
使用 group_by
、summarise
和 reduce
的另一种方式:
m_sum <- function(l) {
reduce(l, `+`) %>% list()
}
group_by(d, g) %>%
summarise(m_sum = m_sum(m)) %>%
select(m_sum) %>%
unlist(recursive = FALSE)
我有一个 dataframe
,其中一列是一个列表,其中包含每一行的矩阵,为该观察定义了一个转换矩阵。
library(tidyverse)
m <- matrix(1:4, ncol = 2)
d <- data_frame(g = c('a', 'a', 'b', 'b', 'b', 'c'),
m = rep(list(m), 6))
这看起来像:
# A tibble: 6 × 2
g m
<chr> <list>
1 a <int [2 × 2]>
2 a <int [2 × 2]>
3 b <int [2 × 2]>
4 b <int [2 × 2]>
5 b <int [2 × 2]>
6 c <int [2 × 2]>
我想得到两个矩阵的列表,a
和 b
,它们是每个分组因子的所有矩阵的总和。我需要这种方法来泛化到任意数量的组,因为我不会提前知道分组因子的数量。
我试过by_slice
和do
,但我所能输出的只是所有矩阵的总和,或者a
或[=15=的总和] 单独的矩阵——不绑定在一个组中。
您可以通过将矩阵嵌套在组中(使用 tidyr 的 nest
)来实现,这会创建一个包含矩阵列表的列表列。然后,您可以使用 purrr 的 map
和 reduce
来总结每个组列表中的矩阵:
results <- d %>%
nest(-g) %>%
mutate(summed = map(data, ~ reduce(.$m, `+`)))
结果:
# A tibble: 3 × 3
g data summed
<chr> <list> <list>
1 a <tibble [2 × 1]> <int [2 × 2]>
2 b <tibble [3 × 1]> <int [2 × 2]>
3 c <tibble [1 × 1]> <int [2 × 2]>
summed
列将在每个组内添加矩阵。
如果您想将其转换为包含矩阵项 a/b/c 的命名列表,您可以这样做:
lst <- results$summed
names(lst) <- results$g
lst
或者:
results %>%
select(-data) %>%
spread(g, summed)
使用 group_by
、summarise
和 reduce
的另一种方式:
m_sum <- function(l) {
reduce(l, `+`) %>% list()
}
group_by(d, g) %>%
summarise(m_sum = m_sum(m)) %>%
select(m_sum) %>%
unlist(recursive = FALSE)