使用 purrr 获取列表中相应矩阵条目的分位数

Use purrr to get quantile of corresponding matrix entries in a list

我有以下 reprex 10 个样本矩阵的列表:


# Sample of 10 3*3 matrices
z1 <- matrix(101:104, nrow = 2, ncol = 2)
z2 <- matrix(201:204, nrow = 2, ncol = 2)
z3 <- matrix(301:304, nrow = 2, ncol = 2)
z4 <- matrix(401:404, nrow = 2, ncol = 2)
z5 <- matrix(501:504, nrow = 2, ncol = 2)
z6 <- matrix(601:604, nrow = 2, ncol = 2)
z7 <- matrix(701:704, nrow = 2, ncol = 2)
z8 <- matrix(801:804, nrow = 2, ncol = 2)
z9 <- matrix(901:904, nrow = 2, ncol = 2)
z10 <- matrix(1001:1004, nrow = 2, ncol = 2)

# Combine all matrices into a single list
za <- list(z1, z2, z3, z4, z5, z6, z7, z8, z9, z10)

我们想要的是将 za 作为输入并获得 2 2*2 matrices 称为 upper_quantilelower_quantile 矩阵。

本质上,这是采用上面的 10 个矩阵列表,并为 对应的条目 取上 97.5% 的分位数。较低的 2.5% 分位数也是如此。

在这种情况下,我们可以手动构造此示例的upper_quantile矩阵,如下所示:

upper_quantile <- matrix(data = c(quantile(x = seq(101, 1001, by = 100), probs = 0.975),
                                  c(quantile(x = seq(102, 1002, by = 100), probs = 0.975)),
                                  c(quantile(x = seq(103, 1003, by = 100), probs = 0.975)),
                                  c(quantile(x = seq(104, 1004, by = 100), probs = 0.975)))
                         , nrow = 2
                         , ncol = 2
                         , byrow = FALSE)

upper_quantile
#>       [,1]  [,2]
#> [1,] 978.5 980.5
#> [2,] 979.5 981.5

我想了解如何使用 purrrtidyverse 工具来做到这一点,因为我一直在努力避免列表上的繁琐循环,并希望自动调整尺寸。

有人可以帮忙吗?

这里有一个稍微笨拙的方法,它至少将所有内容都放在一个管道中。它假设所有矩阵都是相同的维度,这必须是真实的,否则所需的输出没有多大意义。在 purrr 中使用矩阵总是有点奇怪。该方法基本上是使用 flatten 来轻松按我们想要的顺序对单元格进行分组,即每个位置一列。这让我们可以跨列映射以生成另一个向量,然后将该向量放回正确的矩阵中。可能需要对大于 2x2 的矩阵进行一些测试。

我想到的另一种方法是使用 cross 列出所有索引组合,然后类似于您的示例逐个单元格映射和创建矩阵单元格。如果需要可以尝试。

library(tidyverse)
z1 <- matrix(101:104, nrow = 2, ncol = 2)
z2 <- matrix(201:204, nrow = 2, ncol = 2)
z3 <- matrix(301:304, nrow = 2, ncol = 2)
z4 <- matrix(401:404, nrow = 2, ncol = 2)
z5 <- matrix(501:504, nrow = 2, ncol = 2)
z6 <- matrix(601:604, nrow = 2, ncol = 2)
z7 <- matrix(701:704, nrow = 2, ncol = 2)
z8 <- matrix(801:804, nrow = 2, ncol = 2)
z9 <- matrix(901:904, nrow = 2, ncol = 2)
z10 <- matrix(1001:1004, nrow = 2, ncol = 2)

# Combine all matrices into a single list
za <- list(z1, z2, z3, z4, z5, z6, z7, z8, z9, z10)

quant_mat <- function(list, p){
  dim = ncol(list[[1]]) * nrow(list[[1]])
  list %>%
    flatten_int() %>%
    matrix(ncol = dim, byrow = TRUE) %>%
    as_tibble() %>%
    map_dbl(quantile, probs = p) %>%
    matrix(ncol = ncol(list[[1]]))
}

quant_mat(za, 0.975)
#>       [,1]  [,2]
#> [1,] 978.5 980.5
#> [2,] 979.5 981.5
quant_mat(za, 0.025)
#>       [,1]  [,2]
#> [1,] 123.5 125.5
#> [2,] 124.5 126.5

reprex package (v0.2.0) 创建于 2018-03-14。

这应该可以解决使用 tidyverse 的单个分位数的问题:

tibble(za) %>%
  mutate(za = map(za, ~ data.frame(t(flatten_dbl(list(.)))))) %>%
  unnest(za) %>%
  summarize_all(quantile, probs = .975) %>%
  matrix(ncol = 2)