【问题标题】:Compare column values against first row and retain original values in R将列值与第一行进行比较并保留 R 中的原始值
【发布时间】:2019-04-19 00:23:44
【问题描述】:

我有一个很大的(当然)光谱数据矩阵,每列代表不同的质量值,而行代表分析中的样本。一个小例子……

mydata <- matrix(c(c(1.95,6,1,0),c(1.76,3,2,14),c(3.67,2,1.55,7),c(0.57,3,8,12),c(2.33,3,16,2)),nrow = 4, ncol = 5)
rnames <- c("threshold", "S1", "S2", "S3")
row.names(mydata)<- rnames

#           [,1]  [,2] [,3]  [,4]  [,5]
# threshold 1.95  1.76 3.67  0.57  2.33
# S1        6.00  3.00 2.00  3.00  3.00
# S2        1.00  2.00 1.55  8.00 16.00
# S3        0.00 14.00 7.00 12.00  2.00

第一行代表一个阈值,要考虑的样本值必须是阈值的 3 倍。我想将第一行值与列中后续行中的所有值进行比较,如果它是 => 3x 第一行值,则返回单元格值,否则将单元格替换为“0”。

因此,对于那个小样本数据,我希望实现的输出矩阵如下所示:

mydata2 <- matrix(c(c(1.95,6,0,0),c(1.76,0,0,14),c(3.67,0,0,0),c(0.57,3,8,12),c(2.33,0,16,0)),nrow = 4, ncol = 5)
row.names(mydata2) <- rnames

#           [,1]  [,2] [,3]  [,4]  [,5]
# threshold 1.95  1.76 3.67  0.57  2.33
# S1        6.00  0.00 0.00  3.00  0.00
# S2        0.00  0.00 0.00  8.00 16.00
# S3        0.00 14.00 0.00 12.00  0.00

我在想有一种方法可以使用apply 来运行它,但我对 R 的了解并没有延伸到那么远(还)。

我应该注意到,阈值(第一行)最初是一个单独的 1xn 矩阵,它是使用InsertRow 插入到第一行的。如果将数据矩阵与“阈值”矩阵进行比较会更容易,而不是比较矩阵内的行,那就更好了。

感谢您帮助解决这个问题!

【问题讨论】:

    标签: r matrix compare


    【解决方案1】:

    您可以将矩阵的第一行重复到与其余行相同的大小。然后进行比较,得到一个布尔矩阵。将其与原始值相乘。

    mydata[-1, ] <- mydata[-1, ] * (mydata[-1, ] >= 3 * mydata[rep(1, nrow(mydata) - 1), ])
    
    mydata
    #           [,1]  [,2] [,3]  [,4]  [,5]
    # threshold 1.95  1.76 3.67  0.57  2.33
    # S1        6.00  0.00 0.00  3.00  0.00
    # S2        0.00  0.00 0.00  8.00 16.00
    # S3        0.00 14.00 0.00 12.00  0.00
    

    如果您的阈值存储在单独的矩阵中,则可以使用相同的原理。

    【讨论】:

    • 谢谢 Henrik,这是一种快速的方法,我喜欢它可以在不将阈值插入数据矩阵的情况下完成。感谢您的帮助!
    【解决方案2】:

    您绝对可以使用apply,您只需要编写一个函数,其中包含您需要应用于每一列的逻辑。

    apply(mydata, 2, function(x) c(x[1], x[-1]*(x[-1] >= 3*x[1])))
    
    >           [,1]  [,2] [,3]  [,4]  [,5]
    > threshold 1.95  1.76 3.67  0.57  2.33
    > S1        6.00  0.00 0.00  3.00  0.00
    > S2        0.00  0.00 0.00  8.00 16.00
    > S3        0.00 14.00 0.00 12.00  0.00
    

    【讨论】:

    • 谢谢杰克!让我绊倒的是如何简单地引用第一行;我应该想到 x[1],这一切都清楚了!非常感谢。
    • 非常正确。将您的观察纳入我的回答中。
    【解决方案3】:

    上面的问题已经得到了很好的回答,但是如果将阈值行作为单独的矩阵(或等效向量),这是另一种选择。

    threshold <- c(1.95, 1.76, 3.67, 0.57, 2.33)   
    

    假设mydata 是没有threshold 行的原始矩阵:

    t(apply(mydata, 1, function(x) ifelse(x < 3*threshold, 0, x)))
    
    #    [,1] [,2] [,3] [,4] [,5]
    # S1    6    0    0    3    0
    # S2    0    0    0    8   16
    # S3    0   14    0   12    0
    

    【讨论】:

      【解决方案4】:

      sweep 就是为此而生的,而且会很快:

      mydata[-1,][sweep(mydata[-1,], 2, mydata[1,], FUN=`/`) < 3] <- 0
      mydata
      
      #          [,1]  [,2] [,3]  [,4]  [,5]
      #threshold 1.95  1.76 3.67  0.57  2.33
      #S1        6.00  0.00 0.00  3.00  0.00
      #S2        0.00  0.00 0.00  8.00 16.00
      #S3        0.00 14.00 0.00 12.00  0.00
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-27
        相关资源
        最近更新 更多