rnorouzian
rnorouzian

Reputation: 7517

Turn summarise() output into matrices

I was wondering what would be the shortest way to turn the output of my summarise() function into my 3 desired matrices?

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

Desired output:

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)

Upvotes: 1

Views: 89

Answers (1)

akrun
akrun

Reputation: 887118

We can do this in a much simpler way. After grouping by 'group', create a list column in summarise by taking the cov of the matrix created by cbinding the 'y1', 'y2', and then multiply by n() - 1

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

-output

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

Or this can be done with group_split and map

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

In base R, we can use split

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

If we need to create three 'group' objects, use 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

Upvotes: 1

Related Questions