【问题标题】:how to find the most similar columns in a matrix?如何在矩阵中找到最相似的列?
【发布时间】:2015-03-10 14:14:28
【问题描述】:

我有一个矩阵,我想在其中找到那些非常相似的列(我不想找到相同的列

# to generate a matrix
Mat<- matrix(rexp(200, rate=.1), ncol=1000, nrow=400)

我个人想到了“cor”或“all.equal”,我做了如下,但没有奏效。

indexmax <- apply(Mat, MARGIN = 2, function(x) which(cor(x) >= 0.5, arr.ind = TRUE))

我需要的输出是显示哪些列高度相似以及它们的相似程度(可以是相关系数)

相似意味着它们的值在某个阈值内相似(例如超过 75% 的值残差(例如 column1-column2)小于 abs(0.5)

我也很想看看这与相关性有何不同。它们会产生相同的结果吗?

【问题讨论】:

  • 您的意思是类似于 correlated 还是类似于它们的值的差异在某个阈值之内?如果您能详细说明类似的含义,将会很有帮助。
  • 元素?你会认为 1,2,3,4 和 1.1,2.1,3.1,4.1 相似吗? 1,2,3,4 和 4,1,2,3 怎么样?
  • 感谢@Alex 和其他人,我认为找到与在某个阈值内没有差异的那些高度相关的那些不会有太大的不同。我的主要想法是找到在阈值内高度相似的那些,但我很想看看当我们检查相关性时结果是否不同。无论如何,我更新了问题
  • 我可能想错了,但我看到了一个简单的线性回归(将列视为时间序列),结果汇总输出正是您所需要的。如果顺序无关紧要,请事先按升序对它们进行排序。
  • 我建议你计算距离矩阵。以dist(t(Mat))开头。

标签: r


【解决方案1】:

您可以尝试使用相关性(使用更简单的矩阵进行演示)

set.seed(123)
Mat <- matrix(rnorm(300), ncol = 10)
library(matrixcalc)

corr <- cor(Mat)
res <-which(lower.triangle(corr)>.3, arr.ind = TRUE)

data.frame(res[res[,1] != res[,2],], correlation = corr[res[res[,1] != res[,2],]])
  row col correlation
1   8   1   0.3387738
2   6   2   0.3350891

rowcol 实际上都是指原始矩阵中的列。因此,例如第 8 列和第 1 列之间的相关性为0.3387738

【讨论】:

  • 如果行也意味着列,为什么它会写成“行”和“列”:-p
  • 我的意思是它是使用whicharr.ind = TRUE 产生的副产品
  • @Student 你能否也添加最大相关列的相关系数图以及其中的相关值,例如stackoverflow.com/questions/15887212/…
  • 我想你可以自己尝试一下,它在你命名的链接下有描述
【解决方案2】:

我会采用线性回归方法:

Mat<- matrix(rexp(200, rate=.1), ncol=100, nrow=400)
combinations <- combn(1:ncol(Mat), m = 2)
sigma <- NULL
for(i in 1:ncol(combinations)){
  sigma <- c(sigma, summary(lm(Mat[,combinations[1,1]] ~ Mat[,combinations[2,1]]))$sigma)
}
sigma <- data.frame(sigma = sigma, comb_nr = 1:ncol(combinations))

并将剩余标准误差作为可选标准。 您可以按 sigma 进一步排序数据帧并获得最佳/最差组合。

【讨论】:

    【解决方案3】:

    如果您想要一种(不那么优雅)直接的方法,这种方法对于您的大小的矩阵可能非常慢,您可以这样做:

    set.seed(1)
    
    Mat <- matrix(runif(40000), ncol=100, nrow=400)
    
    col.combs <- t(combn(1:ncol(Mat), 2))
    
    similar <- data.frame(Col1=NULL, Col2=NULL, Corr=NULL, Pct.Diff=NULL)
    
    # Compare each pair of columns
    for (k in 1:nrow(col.combs)) {
        i <- col.combs[k, 1]
        j <- col.combs[k, 2]
    
        # Difference within threshold?
        diff.thresh <- (abs(Mat[, i] - Mat[, j]) < 0.5)
    
        pair.corr <- cor(Mat[, 1], Mat[, 2])
    
        if (mean(diff.thresh) > 0.75)
            similar <- rbind(similar, c(i, j, pair.corr, 100*mean(diff.thresh)))
    }
    

    在此示例中,有 2590 对不同的列,其 75% 以上的值彼此相差 0.5(按元素)。您可以通过查看生成的数据框来检查实际差异和相关系数。

    > head(similar)
       Col1  Col2         Corr Pct.Diff
    1     1     2 -0.003187894    76.75
    2     1     3  0.074061019    76.75
    3     1     4  0.082668387    78.00
    4     1     5  0.001713751    75.50
    5     1     8  0.052228907    75.75
    6     1    12 -0.017921978    78.00
    

    也许这不是最好的解决方案,但可以完成工作。

    另外,如果你不确定我为什么使用mean(diff.thresh),那是因为逻辑向量的总和是TRUE 元素的数量。平均值是总和除以长度,这意味着在这种情况下,它是阈值内的值的分数。

    【讨论】:

    • @Nemo:很高兴我能帮上忙。别忘了,你可以接受最适合你的那个。 ;)
    猜你喜欢
    • 2014-06-05
    • 2015-05-07
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    相关资源
    最近更新 更多