删除高度相关的变量

问题描述 投票:0回答:4

我有一个巨大的数据帧 5600 X 6592,我想删除任何相互相关超过 0.99 的变量,我确实知道如何一步一步地做到这一点,即形成一个相关矩阵,对值进行四舍五入,删除类似的并使用索引再次获取我的“减少”数据。

cor(mydata)
mydata <- round(mydata,2)
mydata <- mydata[,!duplicated (mydata)]
## then do the indexing...

我想知道这是否可以通过简短的命令或某些高级功能来完成。我正在学习如何使用 R 语言中强大的工具,这可以避免这么长的不必要的命令

我在想类似的事情

mydata <- mydata[, which(apply(mydata, 2, function(x) !duplicated(round(cor(x),2))))]

抱歉,我知道上面的命令不起作用,但我希望我能够做到这一点。

适用于该问题的播放数据:

mydata <- structure(list(V1 = c(1L, 2L, 5L, 4L, 366L, 65L, 43L, 456L, 876L, 
78L, 687L, 378L, 378L, 34L, 53L, 43L), V2 = c(2L, 2L, 5L, 4L, 
366L, 65L, 43L, 456L, 876L, 78L, 687L, 378L, 378L, 34L, 53L, 
41L), V3 = c(10L, 20L, 10L, 20L, 10L, 20L, 1L, 0L, 1L, 2010L, 
20L, 10L, 10L, 10L, 10L, 10L), V4 = c(2L, 10L, 31L, 2L, 2L, 5L, 
2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 1L), V5 = c(4L, 10L, 31L, 
2L, 2L, 5L, 2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 3L)), .Names = c("V1", 
"V2", "V3", "V4", "V5"), class = "data.frame", row.names = c(NA, 
-16L))

非常感谢

r function subset correlation
4个回答
55
投票

我确信有很多方法可以做到这一点,当然还有比这更好的方法,但这应该可行。我基本上只是将上三角形设置为零,然后删除任何值超过 0.99 的行。

tmp <- cor(data)
tmp[upper.tri(tmp)] <- 0
diag(tmp) <- 0

# Above two commands can be replaced with 
# tmp[!lower.tri(tmp)] <- 0

 
data.new <- 
  data[, !apply(tmp, 2, function(x) any(abs(x) > 0.99, na.rm = TRUE))]
head(data.new)

   V2 V3 V5
1   2 10  4
2   2 20 10
3   5 10 31
4   4 20  2
5 366 10  2
6  65 20  5

53
投票

这是我的 R 代码,这对你会有帮助

library('caret')

df1 = read.csv("stack.csv")

print (df1)

     GA     PN     PC   MBP    GR    AP
1 0.033  6.652  6.681 0.194 0.874 3.177
2 0.034  9.039  6.224 0.194 1.137 3.400
3 0.035 10.936 10.304 1.015 0.911 4.900
4 0.022 10.110  9.603 1.374 0.848 4.566
5 0.035  2.963 17.156 0.599 0.823 9.406
6 0.033 10.872 10.244 1.015 0.574 4.871
7 0.035 21.694 22.389 1.015 0.859 9.259
8 0.035 10.936 10.304 1.015 0.911 4.500


df2 = cor(df1)
hc = findCorrelation(df2, cutoff=0.3) # putt any value as a "cutoff" 
hc = sort(hc)
reduced_Data = df1[,-c(hc)]
print (reduced_Data)

     GA     PN    GR    AP
1 0.033  6.652 0.874 3.177
2 0.034  9.039 1.137 3.400
3 0.035 10.936 0.911 4.900
4 0.022 10.110 0.848 4.566
5 0.035  2.963 0.823 9.406
6 0.033 10.872 0.574 4.871
7 0.035 21.694 0.859 9.259
8 0.035 10.936 0.911 4.500

并将减少的数据写入新的 csv 只需使用:

write.csv(reduced_Data, file = "outfile.csv", row.names = FALSE)

18
投票

@大卫 通过提供 ,代码中的一个小更改可以使其更健壮负相关

abs(x) > 0.99 

而不是仅仅

x > 0.99

data.new <- data[,!apply(tmp,2,function(x) any(abs(x) > 0.99))]

干杯..!!!


0
投票

recipes
包具有
step_corr()
功能来促进这种数据预处理:

library(recipes)

mydata <- structure(list(V1 = c(1L, 2L, 5L, 4L, 366L, 65L, 43L, 456L, 876L, 
                                78L, 687L, 378L, 378L, 34L, 53L, 43L), V2 = c(2L, 2L, 5L, 4L, 
                                                                              366L, 65L, 43L, 456L, 876L, 78L, 687L, 378L, 378L, 34L, 53L, 
                                                                              41L), V3 = c(10L, 20L, 10L, 20L, 10L, 20L, 1L, 0L, 1L, 2010L, 
                                                                                           20L, 10L, 10L, 10L, 10L, 10L), V4 = c(2L, 10L, 31L, 2L, 2L, 5L, 
                                                                                                                                 2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 1L), V5 = c(4L, 10L, 31L, 
                                                                                                                                                                                   2L, 2L, 5L, 2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 3L)), .Names = c("V1", 
                                                                                                                                                                                                                                                      "V2", "V3", "V4", "V5"), class = "data.frame", row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                   -16L))

# initialize pre-processing recipe 
recipe(x = mydata) |> 
  # perform variable selection using 0.99 threshold
  step_corr(recipes::all_numeric(), threshold = 0.99) |> 
  # prepare recipe
  prep() |> 
  # extract data from trained recipe
  juice()
#> # A tibble: 16 × 3
#>       V2    V3    V4
#>    <int> <int> <int>
#>  1     2    10     2
#>  2     2    20    10
#>  3     5    10    31
#>  4     4    20     2
#>  5   366    10     2
#>  6    65    20     5
#>  7    43     1     2
#>  8   456     0     5
#>  9   876     1     1
#> 10    78  2010    52
#> 11   687    20     1
#> 12   378    10     2
#> 13   378    10    52
#> 14    34    10     6
#> 15    53    10     2
#> 16    41    10     1

创建于 2023-11-20,使用 reprex v2.0.2

© www.soinside.com 2019 - 2024. All rights reserved.