为数据集逐行应用函数

时间:2013-10-15 18:51:52

标签: r

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

我有一个矩阵

  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的向量。

3 个答案:

答案 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)