Home > Software design >  Correlation by group and unique pairs
Correlation by group and unique pairs

Time:11-14

I want to do correlations for each unique combination and grouped by another variable. My solutions works for a very small dataset buy imagine more columns it's getting very tedious.

set.seed((13))
df <- data.frame(group = rep(LETTERS[1:3], 3),
                 var1 = rnorm(9, 1),
                 var2 = rnorm(9, 2),
                 var3 = rnorm(9, 1))

df %>% 
  group_by(group) %>%
  summarise(var1_var2 = cor(var1, var2),
  var1_var3 = cor(var1, var3),
  var2_var3 = cor(var2, var3))

I also tried this one, but it doens't work.

df %>%
  group_by(group) %>%
  summarise(cor = cor(df[,2:ncol(df)])) 

CodePudding user response:

Here is an option. Map out all the combos then run a cor test for each group and each var and then pivot wider at the end:

library(tidyverse)

map_dfr(unique(df$group), \(x){
  data.frame(t(combn(c("var1", "var2", "var3"), 2))) |>
    mutate(group = x)
}) |>
  mutate(cor = pmap_dbl(list(X1, X2, group), 
                        ~cor(df[df$group == ..3, ..1], 
                             df[df$group == ..3, ..2]))) |>
  unite(test, X1, X2) |>
  pivot_wider(names_from = test, values_from = cor)
#> # A tibble: 3 x 4
#>   group var1_var2 var1_var3 var2_var3
#>   <chr>     <dbl>     <dbl>     <dbl>
#> 1 A         0.318    -0.476    -0.985
#> 2 B        -0.373    -0.487    -0.628
#> 3 C         0.535     0.991     0.645

CodePudding user response:

Another solution. This works for any number of variables.

library(dplyr)
library(tidyr)
library(purrr)
library(tibble)

set.seed((13))
df <- data.frame(group = rep(LETTERS[1:3], 3),
                 var1 = rnorm(9, 1),
                 var2 = rnorm(9, 2),
                 var3 = rnorm(9, 2))

df %>% 
  select(-group) %>% 
  split(df$group) %>%
  imap_dfr(
    ~ {
      expand.grid(
        first = names(.x),
        second = names(.x),
        stringsAsFactors = FALSE
      ) %>% 
        filter(first < second) %>% 
        rowwise() %>% 
        transmute(
          group = .y,
          pair = paste(first, second, sep = "_"),
          cor = cor(.x[[first]], .x[[second]])
        )
    }
  ) %>% 
  pivot_wider(
    names_from = "pair",
    values_from = "cor"
  )
# # A tibble: 3 × 4
#   group var1_var2 var1_var3 var2_var3
#   <chr>     <dbl>     <dbl>     <dbl>
# 1 A         0.318    -0.476    -0.985
# 2 B        -0.373    -0.487    -0.628
# 3 C         0.535     0.991     0.645
  •  Tags:  
  • r
  • Related