【问题标题】:Create matrix using pairwise calculations between columns in R使用 R 中的列之间的成对计算创建矩阵
【发布时间】:2016-12-16 22:19:46
【问题描述】:

R 新手,在我头上!

我正在尝试编写将结合以下步骤的代码:

a) 找出每行两列之间的最小值

b) 求和找到的最小值

c) 在许多列中执行此操作并构造结果的成对矩阵

步骤 a 和 b 很容易一次处理两列。像这样:

column1 = c(0.08,   0.20,   0.09,   0.19,   0.25,   0.20,   0.00)
column2 = c(0.07,   0.19,   0.09,   0.21,   0.25,   0.19,   0.00)
ps = data.frame(column1, column2)

sum(pmin(ps$column1,ps$column2))

但是对于步骤 c,我很难编写一个代码,该代码将为由 7 行和 32 列组成的数据帧中的每个成对列比较执行此操作。到目前为止,这是我想出的:

d <- replicate(32, rnorm(7))
c <- combn(seq_len(ncol(d)),2)
mat1 <-  matrix(0,ncol=32,nrow=32,dimnames=list(colnames(d),colnames(d)))
v1 <- unlist(lapply(seq_len(ncol(c)),function(i) {d1<-d[,c[,i]];    length(which(d1[,1]!=0 & d1[,2]!=0)) }))

mat1[lower.tri(mat1)]<-v1 

我很确定我的问题在于与“v1”相关的“功能”命令。但我很难过,真的需要一点帮助!

同样,我的目标是在每个成对列比较之间创建一个 32x32 的求和最小值矩阵。

这有意义吗?

非常感谢。

【问题讨论】:

    标签: r matrix multiple-columns


    【解决方案1】:

    outer 函数将执行此操作并为您跟踪簿记,但您必须将其传递给矢量化函数。

    summin <- Vectorize(function(i, j) sum(pmin(ps[[i]], ps[[j]])))
    outer(seq_len(ncol(ps)), seq_len(ncol(ps)), FUN=summin)
    ##      [,1] [,2]
    ## [1,] 1.01 0.98
    ## [2,] 0.98 1.00
    

    我不知道您的 v1 代码中应该发生什么,看起来您不再对最小值求和了。

    如果我要循环自己,我会使用 expand.grid 而不是 combn,因为这样我得到对角线并且不必弄清楚如何填充矩阵的两侧,但要付出代价做所有的计算两次。 (无论如何,计算机做它的速度比我知道如何让它只做一次的速度快两倍。)我也只需将其作为向量,然后再转换为矩阵。

    cc <- expand.grid(seq_len(ncol(d)), seq_len(ncol(d)))
    out <- sapply(seq_len(nrow(cc)), function(k) {
        i <- cc[k,1]
        j <- cc[k,2]
        sum(pmin(d[[i]],d[[j]]))
    })
    out <- matrix(out, ncol=ncol(d))
    

    【讨论】:

    • 嗨亚伦,我使用了你的第一个建议,效果很好!非常感谢您帮助我解决这个问题!
    【解决方案2】:

    我认为您可以尝试以下方法(我不得不承认这是一种简单的方法):

    column1 = c(0.08,   0.20,   0.09,   0.19,   0.25,   0.20,   0.00)
    column2 = c(0.07,   0.19,   0.09,   0.21,   0.25,   0.19,   0.00)
    column3 = c(0.05,   0.49,   0.39,   0.1,   0.5,   0.11,   0.01)
    ps = data.frame(column1, column2, column3)
    
    res <-matrix(nrow = ncol(ps), ncol = ncol(ps))
    
    for (i in (1:ncol(ps))) {
    
      for (j in (i:ncol(ps))){
    
        res[i,j] <- sum(pmin(ps[,i],ps[,j]))
      }
    
    }
    

    为了利用矩阵是对称的这一事实,您可以这样做:

    res[lower.tri(res)] <- t(res)[lower.tri(res)]
    

    (需要注意的一点是,感谢@Aaron 和他的评论,res[lower.tri(res)] &lt;- res[upper.tri(res)] 不起作用,因为 R 正在按列填充值)

    或者(再次感谢 Aaron)您可以这样做(并跳过最后一步):

    for (i in (1:ncol(ps))) {
    
          for (j in (i:ncol(ps))){
    
            res[i,j] <- res[j,i] <- sum(pmin(ps[,i],ps[,j]))
          }
    
        }
    

    【讨论】:

    • 小心,lower.tri 和 upper.tri 不是这样对称的。
    • @Aaron 抱歉,我没明白你能解释一下吗?
    • 添加第四列并尝试一下,您会发现生成的矩阵不是对称的,因为 R 总是按列填充。不过,这是一个很好的答案;我只是建议让你的内循环从 1 开始。
    • 或者,您可以同时填写两个位置:res[j,i] &lt;- res[i,j] &lt;- sum(...)
    • 很高兴听到这个消息,这就是 SO 的全部意义所在。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2020-07-19
    • 1970-01-01
    相关资源
    最近更新 更多