重塑相关矩阵,仅包括每对变量一次

时间:2015-12-10 18:25:09

标签: r

我有一张这样的表:

A   B   C   D   E
7   1   6   8   7
9   3   9   5   9
4   6   2   1   10
10  5   3   4   1
1   3   5   9   3
6   4   8   7   6

我正在查找每个变量与表中每个其他变量的相关性。这是我使用的R代码:

test <- read.csv("D:/AB/test.csv")
iterations <- ncol(test)
correlation <- matrix(ncol = 3 , nrow = iterations * iterations)
for (k in 1:iterations) {
  for (l in 1:iterations){
    corr <- cor(test[,k], test[,l])
    corr_string_A <- names(test[k])
    corr_string_B <- names(test[l])
    correlation[l + ((k-1) * iterations),] <- rbind(corr_string_A, corr_string_B, corr)        
  }
}

以下是我收到的输出:

   Var1 Var2       value
1     A    A  1.00000000
2     B    A  0.50018605
3     C    A -0.35747393
4     D    A -0.25670054
5     E    A -0.02974821
6     A    B  0.50018605
7     B    B  1.00000000
8     C    B  0.56070716
9     D    B  0.46164928
10    E    B  0.16813991
11    A    C -0.35747393
12    B    C  0.56070716
13    C    C  1.00000000
14    D    C  0.52094589
15    E    C  0.23190036
16    A    D -0.25670054
17    B    D  0.46164928
18    C    D  0.52094589
19    D    D  1.00000000
20    E    D -0.39223227
21    A    E -0.02974821
22    B    E  0.16813991
23    C    E  0.23190036
24    D    E -0.39223227
25    E    E  1.00000000

但是,我不想要上三角的值;即,不应出现对角线值,并且每个唯一组合应仅出现一次。最终输出应如下所示:

   Var1 Var2       value
1     B    A  0.50018605
2     C    A -0.35747393
3     D    A -0.25670054
4     E    A -0.02974821
5     C    B  0.56070716
6     D    B  0.46164928
7     E    B  0.16813991
8     D    C  0.52094589
9     E    C  0.23190036
10    E    D -0.39223227

我知道有一些像reshape这样的技术可以实现上面的输出,但是我想让上面的R代码适合并产生上面提到的结果。

我相信&#34; n&#34;在第二个for循环中应该动态改变,这有助于实现这一点。但是我不确定如何使这项工作。

2 个答案:

答案 0 :(得分:6)

You can将您的相关矩阵转换为包含as.data.frameas.table的3列格式,然后可以使用subset限制对角线上方或下方的值

subset(as.data.frame(as.table(cor(dat))),
       match(Var1, names(dat)) > match(Var2, names(dat)))
#    Var1 Var2        Freq
# 2     B    A -0.02299154
# 3     C    A  0.23155350
# 4     D    A -0.28036851
# 5     E    A -0.05230260
# 8     C    B -0.58384036
# 9     D    B -0.80175393
# 10    E    B  0.00000000
# 14    D    C  0.52094589
# 15    E    C  0.23190036
# 20    E    D -0.39223227

请注意,对于较大的数据集,这应该比在变量对上单独调用cor更有效,因为cor是矢量化的,而且显然更少的输入。

如果你真的必须保留循环代码,那么你可以通过对for循环对的一些小改动和一些关于你正在计算的correlation行的书来实现你想要的结果:

iterations <- ncol(test)
correlation <- matrix(ncol = 3 , nrow = choose(iterations, 2))
pos <- 1
for (k in 2:iterations) {
  for (l in 1:(k-1)){
    corr <- cor(test[,k], test[,l])
    corr_string_A <- names(test[k])
    corr_string_B <- names(test[l])
    correlation[pos,] <- rbind(corr_string_A, corr_string_B, corr)        
    pos <- pos+1
  }
}

但是我真的不建议这种循环解决方案;最好使用我提供的单线程,然后再处理所有生成的NA值。

答案 1 :(得分:2)

从OP的循环输出,我们可以对行进行子集化,

df1[!duplicated(t(apply(df1[1:2], 1, sort))) & df1[,1]!=df1[,2],]
#   Var1 Var2       value
#2     B    A  0.50018605
#3     C    A -0.35747393
#4     D    A -0.25670054
#5     E    A -0.02974821
#8     C    B  0.56070716
#9     D    B  0.46164928
#10    E    B  0.16813991
#14    D    C  0.52094589
#15    E    C  0.23190036
#20    E    D -0.39223227

或者正如我在评论中提到的(首先),只需使用

cor(test)