【问题标题】:Calculate bulk pair-wise correlation using purrr and nested data.frame使用 purrr 和嵌套 data.frame 计算批量成对相关性
【发布时间】:2020-07-25 18:58:06
【问题描述】:

我想为 mtcars 中的每个 cyl 计算 "mpg" 与所有其他感兴趣的数值变量之间的成对相关性数据集。我想采用整洁的数据原则。

corrr::correlate() 相当简单。

library(dplyr)
library(tidyr)
library(purrr)
library(corrr)
data(mtcars)

mtcars2 <- mtcars[,1:7] %>%
  group_nest(cyl) %>%
  mutate(cors = map(data, corrr::correlate),
         stretch = map(cors, corrr::stretch)) %>%
  unnest(stretch)

mtcars2 %>%
  filter(x == "mpg")

通过使用corrr::correlate(),已计算出所有可用的成对相关性。我可以使用dplyr::filter() 来选择感兴趣的相关性。

但是,当数据集很大时,大量计算会涉及不需要的相关性,这使得这种方法非常耗时。所以我试着只计算 mpg 与其他人。我对purrr不是很熟悉,下面的代码不起作用。

mtcars2 <- mtcars[,1:7] %>%
  group_nest(cyl) %>%
  mutate(comp = map(data, ~colnames),
         corr = map(comp, ~cor.test(data[["mpg"]], data[[.]])))

【问题讨论】:

    标签: r dplyr correlation tidyr purrr


    【解决方案1】:

    这对你有用吗?我过去曾这样做过,但在较小的数据集上并没有对其进行基准测试,因此不确定性能。我使用pivot_longer 在嵌套之前重塑数据。您传递的变量本质上用作过滤步骤,有点

    mtcars2 <- mtcars[,1:7] %>%
      pivot_longer(c(-mpg, -cyl), names_to = "y.var", values_to = "value" ) %>% 
      group_nest(cyl, y.var) %>%
      mutate(x.var  = "mpg", #just so you  can see this in the output
        cor = map_dbl(data, ~ {cor <- cor.test(.x$mpg, .x$value)
                                    cor$estimate})) %>%
      select(data, cyl, x.var , y.var, cor) %>% 
      arrange(cyl, y.var)
    

    【讨论】:

    • 谢谢。这对我有用。您能否简要解释一下花括号部分?我不明白它是如何工作的。
    【解决方案2】:

    如果你需要使用 cor.test,下面是一个使用 broom 的选项:

    library(broom)
    library(tidyr)
    library(dplyr)
    
    mtcars[,1:7] %>% 
    pivot_longer(-c(mpg,cyl)) %>% 
    group_by(cyl,name) %>% 
    do(tidy(cor.test(.$mpg,.$value)))
    
    # A tibble: 15 x 10
    # Groups:   cyl, name [15]
         cyl name  estimate statistic p.value parameter conf.low conf.high method
       <dbl> <chr>    <dbl>     <dbl>   <dbl>     <int>    <dbl>     <dbl> <chr> 
     1     4 disp   -0.805     -4.07  0.00278         9   -0.947   -0.397  Pears…
     2     4 drat    0.424      1.41  0.193           9   -0.236    0.816  Pears…
     3     4 hp     -0.524     -1.84  0.0984          9   -0.855    0.111  Pears…
     4     4 qsec   -0.236     -0.728 0.485           9   -0.732    0.424  Pears…
     5     4 wt     -0.713     -3.05  0.0137          9   -0.920   -0.198  Pears…
     6     6 disp    0.103      0.232 0.826           5   -0.705    0.794  Pears…
     7     6 drat    0.115      0.258 0.807           5   -0.699    0.799  Pears…
    

    如果您只需要相关性,对于大型数据集,嵌套等可能是昂贵且不必要的,因为您可以简单地执行 cor(,) 并将其融化:

    #define columns to correlate
    cor_vars = setdiff(colnames(mtcars)[1:7],"cyl")
    split(mtcars[,1:7],mtcars$cyl) %>% 
    map_dfr(~data.frame(x="mpg",y=cor_vars,
    cyl=unique(.x$cyl),rho=as.numeric(cor(.x$mpg,.x[,cor_vars]))))
    
         x    y cyl         rho
    1  mpg  mpg   4  1.00000000
    2  mpg disp   4 -0.80523608
    3  mpg   hp   4 -0.52350342
    4  mpg drat   4  0.42423947
    5  mpg   wt   4 -0.71318483
    6  mpg qsec   4 -0.23595389
    7  mpg  mpg   6  1.00000000
    8  mpg disp   6  0.10308269
    9  mpg   hp   6 -0.12706785
    10 mpg drat   6  0.11471598
    11 mpg   wt   6 -0.68154982
    12 mpg qsec   6 -0.41871779
    13 mpg  mpg   8  1.00000000
    14 mpg disp   8 -0.51976704
    15 mpg   hp   8 -0.28363567
    16 mpg drat   8  0.04793248
    17 mpg   wt   8 -0.65035801
    18 mpg qsec   8 -0.10433602
    

    【讨论】:

    • 非常感谢。这是一个很好的解决方案。但是我在理解 do() 函数时遇到了问题。
    • 另外,我想问一下,如果变量 cyl 不是数字,我该如何修改第二个解决方案。
    • 当你做 group_by() 然后说 summarise 或 tally 等。如果你想在 group_by 下的每个组上使用非 dplyr 函数或自定义函数,它将是 do() 。 .r-bloggers.com/dplyr-do-some-tips-for-using-and-programming
    • 不一定是数字,我只用mtcars$cyl来拆分。你注意到了一个好点,我没有在列中排除 cyl 来关联,我现在可以更正..
    • 谢谢。第二种解决方案对于大型数据集非常有用。
    猜你喜欢
    • 2018-10-11
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多