我最近使用了更大的数据集,并开始学习并迁移到data.table以提高聚合/分组的性能。我无法按预期将某些表达式或函数分组。以下是我遇到问题的基本操作组示例。
library(data.table)
category <- rep(1:10, 10)
value <- rnorm(100)
df <- data.frame(category, value)
dt <- data.table(df)
如果我想简单地按类别计算每个组的平均值。这很容易。
dt[,mean(value),by="category"]
category V1
1: 1 -0.67555478
2: 2 -0.50438413
3: 3 0.29093723
4: 4 -0.41684790
5: 5 0.33921764
6: 6 0.01970997
7: 7 -0.23684245
8: 8 -0.04280998
9: 9 0.01838804
10: 10 0.44295978
如果我尝试使用scale函数或者甚至是从自身中减去值的简单表达式,我会遇到问题。忽略分组,我将函数/表达式应用于每一行。以下内容按类别返回所有100行而不是10组。
dt[,scale(value),by="category"]
dt[,value-mean(value),by="category"]
我认为将scale重新设置为返回数字向量而不是矩阵的函数可能有所帮助。
zScore <- function(x) {
z=(x-mean(x,na.rm=TRUE))/sd(x,na.rm = TRUE)
return(z)
}
dt[,zScore(value),by="category"]
category V1
1: 1 -1.45114132
2: 1 -0.35304528
3: 1 -0.94075418
4: 1 1.44454416
5: 1 1.39448268
6: 1 0.55366652
....
97: 10 -0.43190602
98: 10 -0.25409244
99: 10 0.35496694
100: 10 0.57323480
category V1
这也会返回应用于所有行(N = 100)并忽略分组的zScore函数。在使用mean()时,为了让scale()或自定义函数像上面那样使用分组,我缺少什么?
答案 0 :(得分:2)
你在评论中澄清了你想要的相同行为:
ddply(df,"category",transform, zscorebycategory=zScore(value))
给出:
category value zscorebycategory
1 1 0.28860691 0.31565682
2 1 1.17473759 1.33282374
3 1 0.06395503 0.05778463
4 1 1.37825487 1.56643607
etc
您提供的数据表选项提供:
category V1
1: 1 0.31565682
2: 1 1.33282374
3: 1 0.05778463
4: 1 1.56643607
etc
这是完全相同的数据。不过,您还想在结果中重复value
列,并使用更具描述性的内容重命名V1
变量。 data.table为您提供结果中的分组变量,以及您提供的表达式的结果。因此,我们修改它以给出您想要的行:
您
dt[,zScore(value),by="category"]
变为:
dt[,list(value=value, zscorebycategory=zScore(value)),by="category"]
列表中的命名项目成为结果中的列。
plyr = data.table(ddply(df,"category",transform, zscorebycategory=zScore(value)))
dt = dt[,list(value=value, zscorebycategory=zScore(value)),by="category"]
identical(plyr, dt)
> TRUE
(注意我将你的ddply data.frame结果转换为data.table,以允许identical
命令工作。)
答案 1 :(得分:1)
您声称data.table没有分组是错误的:
library(data.table)
category <- rep(1:2, each=4)
value <- c(rep(c(1:2),each=2),rep(c(4,10),each=2))
dt <- data.table(category, value)
category value
1: 1 1
2: 1 1
3: 1 2
4: 1 2
5: 2 4
6: 2 4
7: 2 10
8: 2 10
dt[,value-mean(value),by=category]
category V1
1: 1 -0.5
2: 1 -0.5
3: 1 0.5
4: 1 0.5
5: 2 -3.0
6: 2 -3.0
7: 2 3.0
8: 2 3.0
如果要缩放/转换,这正是您想要的行为,因为这些操作按定义返回与输入大小相同的对象。