equivalent of ave() in tidyverse ecosystem

Viewed 103

I was wondering what would be the equivalent of cov(sapply(dat[-1], ave, dat[1])) in library(tidyverse) in my code below?

library(tidyverse)

(T1 = matrix(c(2,3,5,2, 3,4,4,5),4,2)  )      
colnames(T1) <- c("y1", "y2")

(T2 = matrix(c(4:6, 8,6,7),3,2)  )      
colnames(T2) <- colnames(T1) 

(T3 = matrix(c(7,8,10,9,7, 6,7,8,5,6),5,2)  )      
colnames(T3) <- colnames(T1) 

(dat <- map_df(list(T1,T2,T3), as_tibble, .id = 'group'))

cov(sapply(dat[-1], ave, dat[1])) # equivalent of this in tidyverse

#         y1       y2
#y1 5.624242 2.218182
#y2 2.218182 1.731818
2 Answers

One option could be:

dat %>%
 group_by(across(1)) %>%
 mutate(across(everything(), mean)) %>%
 ungroup() %>%
 select(-1) %>%
 cov()

         y1       y2
y1 5.624242 2.218182
y2 2.218182 1.731818

We can use ave within map, convert to data.frame with _dfc ie. binding columnwise and then apply the cov

library(purrr)
library(dplyr)
map_dfc(dat[-1], ave, dat[1]) %>%
    cov
#         y1       y2
# y1 5.624242 2.218182 
# y2 2.218182 1.731818

Or an option with mutate_all

dat %>%
   group_by(group) %>% 
   mutate_all(mean) %>% 
   ungroup %>%
   select(-group) %>%
   cov

With the updated comment about applying reduce

dat %>%
   group_by(group) %>% 
   summarise(new = list(cov(cur_data()) * (n() - 1)),
         .groups = 'drop') %>%
   pull(new) %>% 
   reduce(`+`)
#    y1  y2
#y1 14.8 1.6
#y2  1.6 9.2
Related