我有一个很大的(当然(光谱数据矩阵,每列代表不同的质量值,行代表分析中的样本。一个小例子。。。
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倍。我想将第一行的值与列中后续行的所有值进行比较,如果单元格值=>是第一行值的3倍,则返回单元格值,否则用"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
将其插入第一行。如果将数据矩阵与"阈值"矩阵进行比较比在矩阵内比较行更容易,那就更好了。
感谢您帮助解决此问题!
您可以将矩阵的第一行重复到与重绑定行相同的大小。然后进行比较,得到一个布尔矩阵。将其与原始值相乘。
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
如果阈值存储在单独的矩阵中,也可以使用相同的原理。
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
您肯定可以使用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
上面已经基本回答了这个问题,但如果将阈值行作为单独的矩阵(或等效向量(,这里还有另一种选择。
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