使用data.table时,请参阅以下列中的列:=赋值

时间:2012-05-25 13:55:53

标签: r data.table

根据Row wise matrix operations in 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)]

不幸的是,这只是返回'columns'向量的平均值而不是它们所引用的列的平均值。有没有办法按编号引用这些列?

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

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

3 个答案:

答案 0 :(得分:4)

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

这种方法比涉及rowMeans()的方法快3-5倍。 (差异是由于rowMeans()'初始耗时的数据帧转换为矩阵,正如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, with=FALSE]))
#    user  system elapsed 
#    0.53    0.14    0.77 

## Check results
# all.equal(x1,x2)
# [1] TRUE

答案 1 :(得分: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, with=FALSE]))
   user  system elapsed 
   0.08    0.00    0.08

解决方案2:首先将其设置为长格式。我认为这更快,主要是因为Matthew在另一个问题中的评论说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

答案 2 :(得分: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])