它很可能是愚蠢的,但我找不到以下问题的(非穷举)解决方法:
我们设置:
data<-data.table(id=c("a","a","a","b","b"),
x1=1:5,
x2=6:10,
x3=11:15)
我想要比较根据“id”分组的每个列变量的均值,然后将它们作为变量附加到数据集中。当然,这么少,我们可以使用语法:
means1<-data[,mean(x1),by=id]
同样对于x2,x3,得到:
id x1 x2 x3 V1 V1.1 V1.2
1: a 1 6 11 2.0 7.0 12.0
2: a 2 7 12 2.0 7.0 12.0
3: a 3 8 13 2.0 7.0 12.0
4: b 4 9 14 4.5 9.5 14.5
5: b 5 10 15 4.5 9.5 14.5
然而,对于较大的集合,我们很想循环。这是我先试过的:
for(nn in 1:3){
data<-data[data[,mean(paste("x",nn,sep="")),by=id]]
}
但是这失败了,我猜是因为即使字符串通常被允许识别列名,平均函数也会尝试在外部运算符之前运行:
Warning messages:
1: In `[.data.table`(data, , mean(paste("x", nn, sep = "")), by = id) :
argument is not numeric or logical: returning NA
所以,下次尝试:
for(nn in 1:3){
data<-data[data[,mean(data[[paste("x",nn,sep="")]]),by=id]]
}
然而,这也失败了,因为平均值首先运行。 (更不用说语法对于曾经在STATA中做类似事情的人来说是非常值得的)所以我们最终得到每个x的整体均值被分配给每个id值:
id x1 x2 x3 V1 V1.1 V1.2
1: a 1 6 11 3 8 13
2: a 2 7 12 3 8 13
3: a 3 8 13 3 8 13
4: b 4 9 14 3 8 13
5: b 5 10 15 3 8 13
那么,我们如何在循环中执行这个简单的任务呢?
这样的语法在类似的调用中对我有用,例如:
for(nn in 1:3){
data[,paste("x_greater_than_4_",nn,sep=""):=(data[[paste("x",nn,sep="")]]>4)]
}
产生我期望的东西:
id x1 x2 x3 x_greater_than_4_1 x_greater_than_4_2 x_greater_than_4_3
1: a 1 6 11 FALSE TRUE TRUE
2: a 2 7 12 FALSE TRUE TRUE
3: a 3 8 13 FALSE TRUE TRUE
4: b 4 9 14 FALSE TRUE TRUE
5: b 5 10 15 TRUE TRUE TRUE
答案 0 :(得分:3)
我首先使用setkey
设置密钥,然后在lapply
表达式中使用j
并自行加入结果。您可以使用.SD
中的lapply
和关联的.SDcols
按数字位置指定列。像这样:
setkey( data , id )
data[ data[ , lapply( .SD , mean ) , keyby = id , .SDcols = 2:4 ] ]
# id x1 x2 x3 x1.1 x2.1 x3.1
#1: a 1 6 11 2.0 7.0 12.0
#2: a 2 7 12 2.0 7.0 12.0
#3: a 3 8 13 2.0 7.0 12.0
#4: b 4 9 14 4.5 9.5 14.5
#5: b 5 10 15 4.5 9.5 14.5
# If you just want the group means use this:
data[ , lapply( .SD , mean ), by = id , .SDcols = 2:4 ]
或者,您可以使用:=
和by
,如下所示,这也可以避免加入:
sd_cols = c("x1", "x2", "x3")
data[, c(paste0("v", 1:3)) := lapply(.SD, mean), by=id, .SDcols=sd_cols]
# id x1 x2 x3 v1 v2 v3
# 1: a 1 6 11 2.0 7.0 12.0
# 2: a 2 7 12 2.0 7.0 12.0
# 3: a 3 8 13 2.0 7.0 12.0
# 4: b 4 9 14 4.5 9.5 14.5
# 5: b 5 10 15 4.5 9.5 14.5
答案 1 :(得分:1)
尝试将aggregate
与公式界面一起使用以获取组均值,然后将merge
用于原始数据:
merge(data,aggregate(.~id,data=data,mean),by="id",suffixes=c("",".mean"))
id x1 x2 x3 x1.mean x2.mean x3.mean
1: a 1 6 11 2.0 7.0 12.0
2: a 2 7 12 2.0 7.0 12.0
3: a 3 8 13 2.0 7.0 12.0
4: b 4 9 14 4.5 9.5 14.5
5: b 5 10 15 4.5 9.5 14.5
答案 2 :(得分:1)
怎么样:
> data[, x1Mean := mean(x1), by=id] # this command updates the data table
> data
id x1 x2 x3 x1Mean
1: a 1 6 11 2.0
2: a 2 7 12 2.0
3: a 3 8 13 2.0
4: b 4 9 14 4.5
5: b 5 10 15 4.5