如何在R中计算所有列之间的相关性并检测高度相关的变量

21

我有一个包含100个变量和3000个观测值的大型数据集。 我想检测那些高度相关或冗余的变量(列),并在数据框中删除维度。 我尝试过这个方法,但它只计算一列与其他列之间的相关性;我总是收到错误消息。

for(i in 1:ncol(predicteurs)){
correlations <- cor(predicteurs[,i],predicteurs[,2])
names(correlations[which.max(abs(correlations))])
}

  Warning messages:
 1: In cor(predicteurs[, i], predicteurs[, 2]) :
the standard deviation is zero
  2: In cor(predicteurs[, i], predicteurs[, 2]) :
 the standard deviation is zero

有人能帮助我吗?

5个回答

37

已更新以适用于更新的tidyverse包..

我会尝试收集相关矩阵。

# install.packages(c('tibble', 'dplyr', 'tidyr'))
library(tibble)
library(dplyr)
library(tidyr)

d <- data.frame(x1=rnorm(10),
                x2=rnorm(10),
                x3=rnorm(10))

d2 <- d %>% 
  as.matrix %>%
  cor %>%
  as.data.frame %>%
  rownames_to_column(var = 'var1') %>%
  gather(var2, value, -var1)

  var1 var2       value
1   x1   x1  1.00000000
2   x1   x2 -0.05936703
3   x1   x3 -0.37479619
4   x2   x1 -0.05936703
5   x2   x2  1.00000000
6   x2   x3  0.43716004
7   x3   x1 -0.37479619
8   x3   x2  0.43716004
9   x3   x3  1.00000000

# .5 is an arbitrary number
filter(d2, value > .5)

# remove duplicates
d2 %>%
  mutate(var_order = paste(var1, var2) %>%
           strsplit(split = ' ') %>%
           map_chr( ~ sort(.x) %>% 
                      paste(collapse = ' '))) %>%
  mutate(cnt = 1) %>%
  group_by(var_order) %>%
  mutate(cumsum = cumsum(cnt)) %>%
  filter(cumsum != 2) %>%
  ungroup %>%
  select(-var_order, -cnt, -cumsum)

  var1  var2   value
1 x1    x1     1     
2 x1    x2    -0.0594
3 x1    x3    -0.375 
4 x2    x2     1     
5 x2    x3     0.437 
6 x3    x3     1     

什么是值?找不到值。 - Charlotte
1
当您melt数据框时,“value”是创建的默认列。在您的环境中是否定义了“d”,“d_cor”和“d_cor_melt”?(如果您分别键入它们,它们是否返回数据框而不发生错误?) - maloneypatr
你是否已经安装了 dplyr?我会将它添加到代码中。 - maloneypatr
很棒,如果它满足了你的需求,请接受我的答案 :) 如果不行,也没关系 :) - maloneypatr
1
通过添加 "d2 <- d2 %>% filter(var1 != var2)",可以保留唯一的组合。 - Andrii
显示剩余3条评论

12

另一个看起来有效的方法可能是:

set.seed(101)
mat = matrix(runif(12), 3)
cor_mat = cor(mat)
cor_mat
#           [,1]       [,2]       [,3]       [,4]
#[1,]  1.0000000  0.1050075  0.9159599 -0.5108936
#[2,]  0.1050075  1.0000000  0.4952340 -0.9085390
#[3,]  0.9159599  0.4952340  1.0000000 -0.8129071
#[4,] -0.5108936 -0.9085390 -0.8129071  1.0000000
which(cor_mat > 0.15 & lower.tri(cor_mat), arr.ind = T, useNames = F)
#     [,1] [,2]
#[1,]    3    1
#[2,]    3    2

9
我也遇到了同样的问题,以下是我解决的方法:
install.packages("Hmisc") # Only run on first use
library(Hmisc)
rawdata <- read.csv("/path/to/your/datafile", sep="\t", stringsAsFactors=FALSE) # In my case the separator in the file was "\t", adjust accordingly.
ccs <- as.matrix(rawdata)
rcorr(ccs, type="pearson") # You can also use "spearman"

这种方法相比其他方法具有优势,它将输出您的相关值相应的p值。

1
在你的代码中第4行(即ccs <- as.matrix(cs)),'cs'是什么? - Tiny_hopper
抱歉!那个“cs”应该是“rawdata”。我想你刚刚发现了一个两年前的复制粘贴错误!我已经更正了答案。 - Stunts

2
你可以使用 corrr 包。例如:
corrr::correlate(your_data, method = "pearson")

1

Tidyverse,再探

这里有另一种使用tidyverse的方法 - 类似于@maloneypatr的方法,但步骤更少。

library(tidyverse)

## reproducible example data
set.seed(20211202)
df_data <- map_dfc(1:5, rnorm, n=10)

df_data %>%
  ## convert to correlation matrix
  as.matrix %>% cor %>%

  ## set redundant to `NA`
  `[<-`(lower.tri(., TRUE), NA) %>%

  ## back to tibble
  as_tibble(rownames="var1") %>%

  ## long format, dropping redundant  
  pivot_longer(cols=-1, names_to="var2", values_to="rho", values_drop_na=TRUE) %>%

  ## descending sort most correlated pairs
  arrange(-abs(rho))

### A tibble: 10 x 3
##   var1  var2       rho
##   <chr> <chr>    <dbl>
## 1 ...1  ...5   0.549  
## 2 ...3  ...5   0.538  
## 3 ...2  ...5   0.304  
## 4 ...2  ...3   0.301  
## 5 ...3  ...4  -0.288  
## 6 ...4  ...5   0.249  
## 7 ...1  ...2  -0.0941 
## 8 ...1  ...3   0.0634 
## 9 ...2  ...4  -0.0627 
##10 ...1  ...4  -0.00761

看起来在知道第1-3列之后,第5列可能不会对方差做出太大的贡献。但是迭代特征选择可能是更合适的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接