我正在尝试为data.table中的某些组返回多个列。我使用一个函数来分隔值列表并计算每个组的向量。我想为这样的表返回这些值
address1, time1, value1
address1, time2, value2
address1, time3, value3
我将time1-time2分组到一个函数中,并希望返回类似这样的内容
address1,sum(value1), mean(value1) (by timegr1)
address1,sum(value2+value3),mean(value2+value3) (by timegr2)
我设法计算了所有的值,只是无法格式化结果,因此它将两个时间组放在不同的行中并保持总和和平均值在同一行。
EDIT 这是代码:
v <- data.table(address =c(1,1,1,1),time=c(1,50,51,52),value=c(1,2,3,4))
fun <- function(time,value) {
data <- data.table(time=time,value=value)
#this split depends on a number of criteria
k <- split(data,c(0,rep(1,nrow(data)-1)))
k1 <- sapply(k,function(x) c(mean(x$value),sum(x$value)))
return(k1)
}
v1 <- v[,fun(time,value),by=address]
V1出现
address V1
1: 1 1
2: 1 1
3: 1 3
4: 1 9
我真的需要像
这样的东西 address mean sum
1: 1 1 1
2: 1 3 9
非常感谢。
答案 0 :(得分:3)
要返回多行,data.table应用的函数应返回向量或向量列表,如下例所示。
library(data.table)
(dat <- data.table(expand.grid(sub=1:4, score=1:4), key="sub"))
# sub score
# 1: 1 1
# 2: 1 2
# 3: 1 3
# 4: 1 4
# 5: 2 1
# 6: 2 2
# 7: 2 3
# 8: 2 4
# 9: 3 1
# 10: 3 2
# 11: 3 3
# 12: 3 4
# 13: 4 1
# 14: 4 2
# 15: 4 3
# 16: 4 4
dat[,list(stat=c("mean","sd"), value=c(mean(score),sd(score))),by=sub]
# sub stat value
# 1: 1 mean 2.500000
# 2: 1 sd 1.290994
# 3: 2 mean 2.500000
# 4: 2 sd 1.290994
# 5: 3 mean 2.500000
# 6: 3 sd 1.290994
# 7: 4 mean 2.500000
# 8: 4 sd 1.290994
答案 1 :(得分:1)
我只能通过两个步骤实现这一目标
fun <- function(x) {
c(0,rep(1,length(x)-1))
}
v <- data.table(address =c(1,1,1,1),time=c(1,50,51,52),value=c(1,2,3,4))
v1 <- v[,group:=fun(time),by=address]
v2 <- v1[,list(mean=mean(value),sum=sum(value)),by=list(address,group)]
address group mean sum
1: 1 0 1 1
2: 1 1 3 9
答案 2 :(得分:1)
这个老问题已经有了一个公认的答案。但是,答案似乎没有重现问题所示的预期结果,或者看起来过于复杂,恕我直言。
如果我理解正确,OP希望按address
和依赖time
的函数对数据进行分组。分组变量的计算可以在传递给by
参数的列表表达式中即时完成。没有必要事先创建单独的group
变量或在函数中使用split()
。
使用data.table
的当前CRAN版本1.10.4-3,解决方案是单行的:
v[, .(mean = mean(value), sum = sum(value)), by = .(address, timegrp = (1:nrow(v)) == 1L)]
address timegrp mean sum 1: 1 TRUE 1 1 2: 1 FALSE 3 9
OP的预期结果不包含第二个分组变量。由于OP选择的配额,这可能只是偶然发生。但是,如果需要删除,可以按如下方式实现:
v[, .(mean = mean(value), sum = sum(value)), by = .(address, timegrp = (1:nrow(v)) == 1L)][
, timegrp := NULL][]
address mean sum 1: 1 1 1 2: 1 3 9
或者,time
可以按
v[, .(mean = mean(value), sum = sum(value)), by = .(address, timegrp = time %/% 10)]
address timegrp mean sum 1: 1 0 1 1 2: 1 5 3 9