2013-10-15 15 views
4

希望能够清楚地解释我想要做什么。为数据集应用行式函数

我有一个矩阵

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)   

我想到了什么样分别计算一切都像

Subsettting第一

onlyABC<-Z[,1:3] 

然后rowMeans适用于每一行

 means<-apply(onlyABC,1,rowMeans) 
数据

而且同样计算分别使用

deviate<-apply(onlyABC,1,SD) 

然后,我现在不知道如何在矩阵“Z”从“手段”减去值列,然后通过“偏离”划分标准偏差。

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

作为施加式到第一行将举一个例子:

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

类似地应用公式以其他行以及和最终得到大小为10的矢量。

+2

你在正确的,可能做的一切F astest方式(使用'matrix'或'data.frame')。一旦你有'手段'和'偏离',只要做'(Z [,1] - 意味着)/偏离“。这样的操作在R中被矢量化。参见Metrics的答案。 – Michele

回答

9
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 
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
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) 
+0

适用于本示例,但我的大型数据集。 – Paul

+2

@Paul如果速度是一个问题,那么你应该在问题中提到。现在,你为什么不把所有的答案都拿回来,并且运行一个基准,并比较不同的时间点? (你可以使用'microbenchmark') – Michele

+0

注意,这个函数有一个错误,并给出错误的结果。它缺少一个paren:它应该是'process < - function(x){(x [[“value”]] - mean(c(x [[“A”]],x [[“B”]] x [[“C”]])))/ sd(c(x [[“A”]],x [[“B”]],x [[“C”]]))}' – ricardo