5

希望能够清楚地解释我想做什么。

我有一个矩阵

  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”中的值列,然后除以“deviate”。

有没有更简单的方法来做到这一点?

例如,将公式应用于第一行将给出:

 row1  32-(19+35+4/3)
       --------------
        SD(19+35+4)

同样,也将公式应用于其他行,最后得到一个大小为 10 的向量。

4

3 回答 3

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
于 2013-10-15T19:20:44.640 回答
3

这不是一个应用问题,因为您想从计算中排除每行的第一列。

这样做的迭代方式是首先创建输出向量,然后将其代入如下:

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')

仅使用 apply 的矢量化方法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
于 2013-10-15T19:08:48.960 回答
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)
于 2013-10-15T19:13:03.527 回答