我最近使用了更大的数据集,并开始学习和迁移到data.table以提高聚合/分组的性能.我无法按预期将某些表达式或函数分组.以下是我遇到问题的基本操作示例. library(data.table)category -
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"]
我认为重新创建比例作为返回数字向量而不是矩阵的函数可能有所帮助.
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()或自定义函数像上面那样使用分组,我缺少什么?
你已在评论中澄清了你想要的相同行为: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
这是完全相同的数据.但是,您还要在结果中重复值列,并使用更具描述性的内容重命名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,以允许相同的命令工作).