Подтвердить что ты не робот

Удалить сильно коррелированные переменные

У меня огромный массив данных 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))

Большое спасибо

4b9b3361

Ответ 1

Я уверен, что есть много способов сделать это и, конечно, лучше, чем это, но это должно сработать. Я просто устанавливаю верхний треугольник равным нулю, а затем удаляю любые строки, которые имеют значения более 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(x > 0.99))]
> 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

Ответ 2

Это мой 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)

Ответ 3

@David Небольшое изменение в вашем коде делает его более надежным отрицательной корреляцией, предоставляя

abs(x) > 0.99 

вместо

x > 0.99

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

веселит..!!!