1

根据R 中的逐行矩阵运算,我想在我拥有的 data.table 上应用逐行函数。我希望每行计算该行中许多列的平均值。我目前的尝试是:

columns <- c(1,5,10,15,20) # Actually obtained via grep
my.data.table[,"average" := mean(columns),with=FALSE] # Or...
my.data.table[,average := mean(columns)]

不幸的是,这只是返回“列”向量的平均值,而不是它们所引用的列的平均值。有没有办法按数字引用这些列?

这是我想要达到的平均值:

key  a b c average
A    5 5 5 5
B    1 2 3 2
C    2 4 9 5
4

3 回答 3

4

另一种选择是构建您真正想要执行的调用,然后eval()DT[]. 这是 data.table FAQ 的第 1.5 和 1.6 节中描述的策略(通过键入查看vignette("datatable-faq"))。

这种方法的运行速度比涉及rowMeans(). (这种差异是由于rowMeans()“将 data.frames 转换为矩阵的初始耗时,正如 Matthew Dowle 在下面的评论中指出的那样。)

## Prepare data
library(data.table)
N <- 1000000
DT <- data.table(ID = 1:N,
                 Year1 = rnorm(N),
                 Year2 = rnorm(N),
                 Year3 = rnorm(N),
                 Year4 = rnorm(N))    
x <- c(2, 3, 4, 5)

## Construct the desired expression:   (Year1 + Year2 + Year3 + Year4)/4
addCols <- paste(names(DT)[x], collapse = " + ")
e <- paste("(", addCols, ")/", length(x), sep="")
e <- parse(text=e)[[1]]

## Compare timings
system.time(x2 <- DT[,eval(e)])
#    user  system elapsed 
#    0.11    0.00    0.11 
system.time(x1 <- rowMeans(DT[, ..x]))
#    user  system elapsed 
#    0.53    0.14    0.77 

## Check results
# all.equal(x1,x2)
# [1] TRUE
于 2012-05-25T16:06:06.570 回答
3

这里有两种可能的解决方案。它们基本上都来自您已经提供的链接,所以也许我错过了这个问题的一些东西。开始了:

解决方案 1(使用rowMeans):

library(data.table)
N <- 1000000
my.data.table <- data.table(ID = 1:N,
                            Year1 = rnorm(N),
                            Year2 = rnorm(N),
                            Year3 = rnorm(N),
                            Year4 = rnorm(N))

x <- c(2, 3, 4, 5)
system.time(x1 <- rowMeans(my.data.table[, ..x]))
   user  system elapsed 
   0.08    0.00    0.08

解决方案2:首先将其转换为长格式。我认为这更快,主要是因为马修在另一个问题中的评论说这data.table是针对DT[,mad(variable),by=group]语法的。我想我错过了一些东西,但看不到什么:

library(reshape2)
DT <- as.data.table(melt(as.data.frame(my.data.table), id.var="ID"))
setkey(DT, ID)
system.time(x2 <- DT[, mean(value), by="ID"][[2]])
   user  system elapsed 
  11.28    0.00   11.33 
all.equal(x1, x2)
[1] TRUE
于 2012-05-25T14:36:12.510 回答
1

好吧,再来一次……

这样可以吗

x<-1:5
y<-1:5
z<-1:5
xy<-data.table(x,y,z)
id<-c("x","y")
newxy<-rowMeans(xy[, id, with=FALSE])
于 2012-05-25T14:02:45.630 回答