【问题标题】:Turn summarise() output into matrices将 summarise() 输出转换为矩阵
【发布时间】:2021-05-17 22:27:01
【问题描述】:

我想知道将summarise() 函数的输出转换为我想要的 3 个矩阵的最短方法是什么?

z <- "group    y1    y2
1 1         2     3
2 1         3     4
3 1         5     4
4 1         2     5
5 2         4     8
6 2         5     6
7 2         6     7
8 3         7     6
9 3         8     7
10 3        10     8
11 3         9     5
12 3         7     6"

dat <- read.table(text = z, header = T)

dat %>% 
  group_by(group) %>%
  summarise(cov = cov(y1, y2) * (n() - 1),
            across(c(y1, y2), ~ var(.) * (n() - 1)))

#  group   DV1   DV2   cov
#1     1   6     2     0  
#2     2   2     2    -1  
#3     3   6.8   5.2   2.6

期望的输出:

group1 = matrix(c(6,0,0,2),2)
group2 = matrix(c(2,-1,-1,2),2)
group3 = matrix(c(6.8,2.6,2.6,5.2),2)

【问题讨论】:

    标签: r dataframe matrix dplyr tidyverse


    【解决方案1】:

    我们可以用一种更简单的方式来做到这一点。按“组”分组后,在summarise 中创建一个list 列,方法是将cbind 创建的cov 中的cov 与“y1”、“y2”相乘,然后乘以n() - 1

    out <-  dat %>% 
                group_by(group) %>%
                summarise(mat1 = list(cov(cbind(y1, y2)) * (n() - 1)), 
                   .groups = 'drop')
    

    -输出

    out$mat1
    #[[1]]
    #     [,1] [,2]
    #[1,]    6    0
    #[2,]    0    2
    
    #[[2]]
    #     [,1] [,2]
    #[1,]    2   -1
    #[2,]   -1    2
    
    #[[3]]
    #     [,1] [,2]
    #[1,]  6.8  2.6
    #[2,]  2.6  5.2
    

    或者这可以通过group_splitmap 来完成

    library(purrr)
    dat %>%
         group_split(group, .keep = FALSE) %>%
         map(~ cov(.x) * (nrow(.x) - 1))
    

    base R,我们可以使用split

    lapply(split(dat[c('y1', 'y2')], dat$group), 
            function(x) cov(x) * (nrow(x) - 1))
    

    如果我们需要创建三个“组”对象,请使用list2env

    library(stringr)
    deframe(out) %>%
         set_names(str_c('group', seq_along(.))) %>% 
         list2env(.GlobalEnv)
    
    
    
    group1
    #     [,1] [,2]
    #[1,]    6    0
    #[2,]    0    2
    group2
    #     [,1] [,2]
    #[1,]    2   -1
    #[2,]   -1    2
    
    group3
    #     [,1] [,2]
    #[1,]  6.8  2.6
    #[2,]  2.6  5.2
    

    【讨论】:

    • @rnorouzian 如果您查看帖子中的摘要输出,我们只有 3 列,但在矩阵中,我们希望重复其中一条对角线。所以,我复制了第一列(组除外),即“co”两次,并在matrix 中使用它
    • @rnorouzian 我想更新的更简单的方法会更有用
    • 这太好了,我们能不能也快点sum()这些矩阵?
    • 您想对矩阵的元素求和(purrr::map_dbl(out$mat1,sum))还是将它们相加(Reduce("+", out$mat1))?
    • @rnorouzian 总和部分不清楚。是元素方面的(正如 BenBolker 提到的那样,它将与 Reduce 一起使用)还是遍历列表并将总和作为 lapply(out$mat1, sum)
    猜你喜欢
    • 1970-01-01
    • 2017-08-30
    • 2021-02-28
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多