r - 是否有 R 函数可以从矩阵中获取所有可能的子矩阵?
问题描述
如果我有一个像下面这样的矩阵,我想根据第一列对其进行分组并创建子矩阵的所有组合,其中子矩阵的行数将等于创建的组数,如示例所示。在 R 中有没有有效的方法来做到这一点?我试图使用 tidyverse group_by(),但找不到正确的函数来获取子矩阵。
# Input Matrix
[,1] [,2] [,3]
[1,] "a" "1" "6"
[2,] "a" "5" "9"
[3,] "c" "7" "4"
[4,] "b" "5" "4"
[5,] "a" "6" "4"
[6,] "b" "6" "4"
[7,] "b" "4" "3"
[8,] "c" "1" "2"
[9,] "d" "9" "9"
# Want to create a Group Matrix
grp1
[1,] "a" "1" "6"
[2,] "a" "5" "9"
[5,] "a" "6" "4"
grp2
[4,] "b" "5" "4"
[6,] "b" "6" "4"
[7,] "b" "4" "3"
grp3
[3,] "c" "7" "4"
[8,] "c" "1" "2"
grp4
[9,] "d" "9" "9"
# Then create - All Combination Submatrix
s1
[1,] "a" "1" "6"
[4,] "b" "5" "4"
[3,] "c" "7" "4"
[9,] "d" "9" "9"
s2
[1,] "a" "1" "6"
[6,] "b" "6" "4"
[8,] "c" "1" "2"
[9,] "d" "9" "9"
s3
[1,] "a" "1" "6"
[7,] "b" "4" "3"
[3,] "c" "7" "4"
[9,] "d" "9" "9"
and so on...
解决方案
我们可以用 dplyr 和 purrr 来做到这一点。
首先,要按组获取单独的数据帧,我们可以使用 dplyr 的group_split
:
library(dplyr)
library(purrr)
g <- c("a", "a", "c", "b", "a", "b", "b", "c", "d")
m1 <- c(1, 5, 7, 5, 6, 6, 4, 1, 9)
m2 <- c(6, 9, 4, 4, 4, 4, 3, 2, 9)
df <- tibble(g = g, m1 = m1, m2 = m2)
df %>%
group_split(g)
#> [[1]]
#> # A tibble: 3 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 a 1 6
#> 2 a 5 9
#> 3 a 6 4
#>
#> .......
#>
#> [[4]]
#> # A tibble: 1 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 d 9 9
#>
#> attr(,"ptype")
#> # A tibble: 0 x 3
#> # … with 3 variables: g <chr>, m1 <dbl>, m2 <dbl>
要获取每个组的所有行组合,我们将遵循以下过程:
- 按我们想要的变量分组 (
group_by(g)
) - 提取变量的每个值
g
出现的行号列表(使用 dplyr'sgroup_rows
)。列表的第一个元素将是一个列表,其中包含 g 等于“a”的行号,g 等于“b”的第二个元素,等等。 - 使用 purrr's 展开此列表中元素的所有组合
cross
。这为我们提供了一个列表,其中每个元素都包含所需子矩阵之一的行。 - 使用每组索引对矩阵进行子集,一次使用 purrr's
map
。根据需要,这为我们留下了所有可能的子矩阵的列表。
df %>%
group_by(g) %>%
group_rows() %>%
cross() %>%
map(., ~df %>% slice(flatten_int(.x)))
#> [[1]]
#> # A tibble: 4 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 a 1 6
#> 2 b 5 4
#> 3 c 7 4
#> 4 d 9 9
#>
#> [[2]]
#> # A tibble: 4 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 a 5 9
#> 2 b 5 4
#> 3 c 7 4
#> 4 d 9 9
#>
#> [[3]]
#> # A tibble: 4 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 a 6 4
#> 2 b 5 4
#> 3 c 7 4
#> 4 d 9 9
#>
#> .......
#>
#> [[18]]
#> # A tibble: 4 x 3
#> g m1 m2
#> <chr> <dbl> <dbl>
#> 1 a 6 4
#> 2 b 4 3
#> 3 c 1 2
#> 4 d 9 9
请记住,尽管您将创建的子矩阵的数量随着每个组中的行数的乘积而增长g
(组'a'中的行数乘以组'b'中的行数,乘以.. .)。
例如,如果您只有 16 个组,每个组有 10 行,cross
将尝试创建一个长度为 10^16 的整数向量。这个长度大于 R 规定的 52 位最大值,更确切地说,远远大于你的机器在内存中可以容纳的长度——这样的向量需要大约 37 PB。
推荐阅读
- maven - 删除万能插件
- docker - 如何使用 docker 配置 Corda 网络(使用 YAML 文件)
- c# - C# - Asp.net Web API 测试项目 - 如何模拟用户并在特定用户下运行测试用例
- c# - log4net.Appender 中缺少 AdoNetAppender 类
- spring-boot - 使用 H2 和 JPA 的 Spring Boot 集成测试失败
- reactjs - 反应 - 未找到模块
- sails.js - 从 Sails + swagger autogenation 中删除一些路线
- python - 在 Keras 的 ImageDataGenerator.flow_from_directory 中处理无效/损坏的图像文件
- reporting-services - 合并 SSRS 中的行
- rust - 为什么在调试和发布模式下存储和加载 AVX2 256 位向量会产生不同的结果?