R 将j应用于data.table中的两组i和by
我有一个data.table,如下所示:R 将j应用于data.table中的两组i和by,r,data.table,R,Data.table,我有一个data.table,如下所示: dt=data.table(ID=rep(1:6,each=2),Set=c("a","b"),Value=rnorm(12)) 我想要一个data.table解决方案,其结果如下: dt.test=data.table(ID=dt[Set=="a",Value,by=ID][order(ID),ID],Value=dt[Set=="a",Value,by=ID][order(ID),Value]-dt[Set=="b",Value,by=ID][or
dt=data.table(ID=rep(1:6,each=2),Set=c("a","b"),Value=rnorm(12))
我想要一个data.table解决方案,其结果如下:
dt.test=data.table(ID=dt[Set=="a",Value,by=ID][order(ID),ID],Value=dt[Set=="a",Value,by=ID][order(ID),Value]-dt[Set=="b",Value,by=ID][order(ID),Value])
但是我不想为了使值
而必须调用dt
两次
任何帮助都将不胜感激。您可以:
# reshape the data table
df.test <- dcast(data = dt, ID ~ Set, value.var = 'Value')
# create new column
df.test <- df.test[, Values := a - b][,.(ID, Values)]
#重塑数据表
df.test您可以执行以下操作:
# reshape the data table
df.test <- dcast(data = dt, ID ~ Set, value.var = 'Value')
# create new column
df.test <- df.test[, Values := a - b][,.(ID, Values)]
#重塑数据表
df.test迄今为止最快的解决方案:
dt[ dt[, .I[1], ID ]$V1][, `:=`(Set = NULL, Value = Value - dt[dt[, .I[2], ID ]$V1]$Value)][]
基准
microbenchmark::microbenchmark(
ricardo.solution = data.table(ID=dt[Set=="a",Value,by=ID][order(ID),ID],Value=dt[Set=="a",Value,by=ID][order(ID),Value]-dt[Set=="b",Value,by=ID][order(ID),Value]),
YOLO.solution = {df.test <- dcast(data = dt, ID ~ Set, value.var = 'Value')
df.test <- df.test[, Values := a - b][,.(ID, Values)]},
this.answer = dt[ dt[, .I[1], ID ]$V1][, `:=`(Set = NULL, Value = Value - dt[dt[, .I[2], ID ]$V1]$Value)][]
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# ricardo.solution 5.197409 5.338703 6.024780 5.526993 5.748874 45.018507 100
# YOLO.solution 2.617082 2.719060 3.006002 2.784585 2.948021 17.891175 100
# this.answer 1.432812 1.479057 1.525045 1.502857 1.539461 1.896759 100
microbenchmark::microbenchmark(
ricardo.solution=data.table(ID=dt[Set==“a”,Value,by=ID][order(ID),ID],Value=dt[Set==“a”,Value,by=ID][order(ID),Value]--dt[Set==“b”,Value,by=ID][order(ID),Value]),
YOLO.solution={df.test迄今为止最快的解决方案:
dt[ dt[, .I[1], ID ]$V1][, `:=`(Set = NULL, Value = Value - dt[dt[, .I[2], ID ]$V1]$Value)][]
基准
microbenchmark::microbenchmark(
ricardo.solution = data.table(ID=dt[Set=="a",Value,by=ID][order(ID),ID],Value=dt[Set=="a",Value,by=ID][order(ID),Value]-dt[Set=="b",Value,by=ID][order(ID),Value]),
YOLO.solution = {df.test <- dcast(data = dt, ID ~ Set, value.var = 'Value')
df.test <- df.test[, Values := a - b][,.(ID, Values)]},
this.answer = dt[ dt[, .I[1], ID ]$V1][, `:=`(Set = NULL, Value = Value - dt[dt[, .I[2], ID ]$V1]$Value)][]
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# ricardo.solution 5.197409 5.338703 6.024780 5.526993 5.748874 45.018507 100
# YOLO.solution 2.617082 2.719060 3.006002 2.784585 2.948021 17.891175 100
# this.answer 1.432812 1.479057 1.525045 1.502857 1.539461 1.896759 100
microbenchmark::microbenchmark(
ricardo.solution=data.table(ID=dt[Set==“a”,Value,by=ID][order(ID),ID],Value=dt[Set==“a”,Value,by=ID][order(ID),Value]--dt[Set==“b”,Value,by=ID][order(ID),Value]),
YOLO.solution={df.test使用shift
处理不同后续行中相同列的值:
dt[, .(Value = Value - shift(Value, type = "lead")), by = ID][!is.na(Value), ]
导致
ID Value
1: 1 0.7455129
2: 2 -0.1529171
3: 3 -1.0823840
4: 4 1.5533354
5: 5 -1.2234450
6: 6 -0.5912473
基准测试(由于@Wimpel提供了代码库而受到赞扬!):
请注意,对于这少量的输入数据,基准不是很有代表性…使用shift
处理不同后续行中相同列的值:
dt[, .(Value = Value - shift(Value, type = "lead")), by = ID][!is.na(Value), ]
导致
ID Value
1: 1 0.7455129
2: 2 -0.1529171
3: 3 -1.0823840
4: 4 1.5533354
5: 5 -1.2234450
6: 6 -0.5912473
基准测试(由于@Wimpel提供了代码库而受到赞扬!):
请注意,对于这少量的输入数据,基准并不是很有代表性…重塑并不是真正的data.table解决方案。第二个会给我一个相同大小的dt,这不是我想要的。无论如何,谢谢。您应该运行这段代码,它给出的答案与您的问题中预期的完全相同。@RicardoFernandesCamposdcast
是一个data.table
解决方案,在这种情况下,因为它被覆盖了,请参见?data.table::dcast
@R Yoda,我不知道dcast有data.table版本。谢谢。而且,很抱歉,@YOLO,我想我还没有正确地查看您的答案。重塑不是一个真正的data.table解决方案。第二个是给我一个大小相同的dt,这不是我想要的。无论如何,谢谢。你应该运行这个代码,它给出的答案与你的问题中预期的完全相同。@RicardoFernandesCamposdcast
是一个数据。表解决方案在这种情况下,因为它被覆盖了,请参见?data.table::dcast
@R Yoda,我不知道dcast有一个data.table版本。谢谢。而且,对不起,@YOLO,我想我没有正确地看你的答案。我可以假设每个ID正好出现两次并且顺序正确吗?ashift
将是自然的…我可以假设每个ID正好出现两次并且顺序正确吗?ashift
将是自然的。。。