корреляционная матрица с p-значением в R - PullRequest
0 голосов
/ 20 мая 2018

Предположим, я хочу провести матрицу корреляции

library(dplyr)

data(iris)
iris %>% 
  select_if(is.numeric) %>%
  cor(y =iris$Petal.Width, method = "spearman") %>%  round(2)

Теперь мы видим

              [,1]
Sepal.Length  0.83
Sepal.Width  -0.29
Petal.Length  0.94
Petal.Width   1.00

Я хочу, чтобы статистически значимая корреляция была отмечена *, где

*<0,05
**<0,01
*** <0,001

как это сделать?

Ответы [ 3 ]

0 голосов
/ 20 мая 2018

Вы можете адаптировать corstarsl() к вашим потребностям.

corFun <- function (x) {
  library(Hmisc)
  x <- as.matrix(x)
  R <- rcorr(x, type="spearman")$r
  p <- rcorr(x, type="spearman")$P
  stars <- ifelse(p < 0.001, "***", ifelse(p < 0.01, "** ", 
                                             ifelse(p < 0.05, "* ", " ")))
  R <- format(round(cbind(rep(-1.11, ncol(x)), R), 2))[, -1]
  Rnew <- matrix(paste(R, stars, sep = ""), ncol = ncol(x))
  diag(Rnew) <- paste(diag(R), " ", sep = "")
  rownames(Rnew) <- colnames(x)
  colnames(Rnew) <- paste(colnames(x), "", sep = "")
  Rnew <- as.matrix(Rnew)
  Rnew <- as.data.frame(Rnew)
  return(Rnew)
}

Урожай

> data.frame(r=corFun(iris[, -5])[, 4])
                    r
Sepal.Length  0.83***
Sepal.Width  -0.29***
Petal.Length  0.94***
Petal.Width     1.00 
0 голосов
/ 20 мая 2018

Вот два варианта tidyverse, которые оба используют tidy из broom.Использование tidy извлечет оценки и значения p, поэтому вам не нужно делать это вручную.Я сделал вектор разрывов для разных уровней значимости, которые вы хотите показать, чтобы вы могли использовать cut, чтобы легко вырезать и пометить значения p;хранение этого в именованном векторе также делает его более повторяемым.

Первый раз, когда я использовал cor.test, что указывает на метод tidy.htest.Во второй раз я использовал rcorr из Hmisc, что указывает на метод tidy.rcorr.

В первом случае я gather преобразовал фрейм данных в длинный формат, чтобы сравнить каждую меру сPetal.Width;во втором случае, для которого требовалась матрица, я использовал полный набор данных, а затем отфильтровал для любого столбца, содержащего Petal.Width.

library(tidyverse)

sig_breaks <- c(zero = 0, "***" = 0.001, "**" = 0.01, "*" = 0.05, NS = Inf)

iris %>%
  as_tibble() %>%
  select_if(is.numeric) %>%
  gather(key = measure, value = value, -Petal.Width) %>%
  group_by(measure) %>%
  do(mtx = cor.test(.$value, .$Petal.Width, method = "spearman")) %>%
  broom::tidy(mtx) %>%
  mutate(stars = cut(p.value, breaks = sig_breaks, include.lowest = T, labels = names(sig_breaks)[2:5]))
#> # A tibble: 3 x 7
#> # Groups:   measure [3]
#>   measure      estimate statistic  p.value method        alternative stars
#>   <chr>           <dbl>     <dbl>    <dbl> <fct>         <fct>       <fct>
#> 1 Petal.Length    0.938    35061. 8.16e-70 Spearman's r… two.sided   ***  
#> 2 Sepal.Length    0.834    93208. 4.19e-40 Spearman's r… two.sided   ***  
#> 3 Sepal.Width    -0.289   725048. 3.34e- 4 Spearman's r… two.sided   ***

iris %>%
  select_if(is.numeric) %>%
  as.matrix() %>%
  Hmisc::rcorr(type = "spearman") %>%
  broom::tidy() %>%
  filter(column1 == "Petal.Width" | column2 == "Petal.Width") %>%
  mutate(stars = cut(p.value, breaks = sig_breaks, include.lowest = T, labels = names(sig_breaks)[2:5]))
#>        column1     column2   estimate   n      p.value stars
#> 1 Sepal.Length Petal.Width  0.8342888 150 0.0000000000   ***
#> 2  Sepal.Width Petal.Width -0.2890317 150 0.0003342981   ***
#> 3 Petal.Length Petal.Width  0.9376668 150 0.0000000000   ***

, созданного в 2018-05-20 пакетом prex (v0.2.0).

0 голосов
/ 20 мая 2018

Решение с использованием .Мы можем преобразовать фрейм данных в длинный формат, создать столбец списка, используя nest, а затем использовать map для выполнения cor.test для каждого подмножества.После этого map_dbl может извлечь значение P, указав имя "p.value".dat1 - окончательный результат.

library(tidyverse)

data(iris)
dat1 <- iris %>% 
  select_if(is.numeric) %>%
  gather(Column, Value, -Petal.Width) %>%
  group_by(Column) %>%
  nest() %>%
  mutate(Cor = map(data, ~cor.test(.x$Value, .x$Petal.Width, method = "spearman"))) %>%
  mutate(Estimate = round(map_dbl(Cor, "estimate"), 2), 
         P_Value = map_dbl(Cor, "p.value"))

dat1
# # A tibble: 3 x 5
#   Column       data               Cor         Estimate  P_Value
#   <chr>        <list>             <list>         <dbl>    <dbl>
# 1 Sepal.Length <tibble [150 x 2]> <S3: htest>    0.83  4.19e-40
# 2 Sepal.Width  <tibble [150 x 2]> <S3: htest>   -0.290 3.34e- 4
# 3 Petal.Length <tibble [150 x 2]> <S3: htest>    0.94  8.16e-70

Если вам не нужны столбцы списка, вы можете использовать select для их удаления.

dat1 %>% select(-data, -Cor)
# # A tibble: 3 x 3
#   Column       Estimate  P_Value
#   <chr>           <dbl>    <dbl>
# 1 Sepal.Length    0.83  4.19e-40
# 2 Sepal.Width    -0.290 3.34e- 4
# 3 Petal.Length    0.94  8.16e-70

Теперь мы можем использоватьmutate и case_when для добавления метки для отображения значимости.

dat2 <- dat1 %>%
  select(-data, -Cor) %>%
  mutate(Significance = case_when(
    P_Value < 0.001  ~ "*** <0,001",
    P_Value < 0.01   ~ "** <0,01",
    P_Value < 0.05   ~ "*<0,05",
    TRUE             ~ "Not Significant"
  ))
dat2
# # A tibble: 3 x 4
#   Column       Estimate  P_Value Significance
#   <chr>           <dbl>    <dbl> <chr>       
# 1 Sepal.Length    0.83  4.19e-40 *** <0,001  
# 2 Sepal.Width    -0.290 3.34e- 4 *** <0,001  
# 3 Petal.Length    0.94  8.16e-70 *** <0,001 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...