希望能够清楚地解释我想做什么。
我有一个矩阵
Z<-matrix(sample(1:40),ncol=4)
colnames(Z)<-c("value","A","B","C")
I would like to apply the following formula to each row in the dataset.
Process = value - rowmean (A,B,C)
------------------------------------
row-wise Standard deviation (A,B,C)
我想到了像
那样单独计算所有内容的东西首先对数据进行子集
onlyABC<-Z[,1:3]
然后将rowMeans应用于每一行
means<-apply(onlyABC,1,rowMeans)
同样使用
分别计算标准偏差 deviate<-apply(onlyABC,1,SD)
然后我现在不知道如何从'means'中减去矩阵'z'中的value列,然后除以'deviate'。
有没有更简单的方法来做到这一点?
作为一个例子,将公式应用于第一行将给出:
row1 32-(19+35+4/3)
--------------
SD(19+35+4)
同样将公式应用于其他行,最后得到一个大小为10的向量。
答案 0 :(得分:10)
ksd<-apply(Z[,-1],1,sd)
kmean<-rowMeans(Z[,-1])
Z[,1]<-(Z[,1]-kmean)/ksd
> Z
value A B C
[1,] 0.88181533 26 4 31
[2,] -0.04364358 17 22 7
[3,] 2.21200505 25 13 18
[4,] 0.50951017 8 34 40
[5,] 0.03866223 12 6 23
[6,] -0.64018440 29 16 30
[7,] -0.40927275 39 35 9
[8,] -0.65103077 24 5 1
[9,] 0.89658092 37 27 3
[10,] 0.26360896 11 10 28
答案 1 :(得分:2)
这不是一个很大的应用问题,因为您要从计算中排除每一行的第一列。
这样做的迭代方法是首先创建输出向量,然后按如下方式替换它:
tranZ <- vector('numeric', length = nrow(Z))
for (i in 1:nrow(Z)) {
tranZ[i] <- (Z[i,1] - mean(Z[i,-1])) / sd(Z[i,-1])
}
如果你有一个大的数据集,我建议使用矢量化的力量 - 尝试以下方法:
(Z[,1] - rowMeans(Z[,-1])) / apply(Z[, -1], 1, sd)
或vapply
:
tranZ_v <- vapply(1:nrow(Z), function(X) (Z[X, 1] - mean(Z[X, -1])) / sd(Z[X, -1]),
FUN.VALUE = numeric(1))
在这种情况下使用*apply
系列的关键是控制应用程序 - 为此我遍历1:nrow(Z)
而不是对象本身:在函数中调用对象。
<强>基准强>
require(rbenchmark)
process <- function(x) {
(x[["value"]] - mean(c(x[["A"]], x[["B"]], x[["C"]]))) / sd(c(x[["A"]], x[["B"]], x[["C"]]))
}
p2 <- function(x) {
(x[1] - mean(x[-1])) / sd(x[-1])
}
apply_fun <- function() apply(Z, 1, process)
apply_fun2 <- function() apply(Z, 1, p2)
apply_sd <- function() (Z[,1] - rowMeans(Z[,-1])) / apply(Z[, -1], 1, sd)
vapply_anon <- function() vapply(1:nrow(Z), FUN = function(X) (Z[X, 1] - mean(Z[X, -1])) / sd(Z[X, -1]),
FUN.VALUE = numeric(1))
bb <- benchmark(apply_fun(), apply_fun2(), apply_sd(), vapply_anon(),
columns = c('test', 'elapsed', 'relative'),
replications = 100,
order = 'elapsed')
使用仅适用sd
的矢量化方法最快:
> bb
test elapsed relative
3 apply_sd() 0.021 1.000
4 vapply_anon() 0.030 1.429
1 apply_fun() 0.033 1.571
2 apply_fun2() 0.034 1.619
答案 2 :(得分:2)
process <- function(x) {
(x[["value"]] - mean(c(x[["A"]], x[["B"]], x[["C"]])) / sd(c(x[["A"]], x[["B"]], x[["C"]])))
}
apply(Z, 1, process)