仅为每个类别中的最高日期重新计算列

时间:2013-05-21 19:11:19

标签: r data.table

我想仅针对某些行重新计算data.table中的列,具体取决于Condition,类别(Cat)和Date

只有在Condition==TRUE时才有资格重新计算一行。在Condition==TRUE的所有行中,只应选择相应Date的{​​{1}}行最高的行。

简化示例:

Cat

我发现了如何提取行的 DF = data.frame(Cat=rep(c("A","B","C"),each=3), Date=rep(c("01-08-2013","01-07-2013","01-04-2013"),3), Condition=c(TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE), Data1=c(1:9), Data2=rep(c(1:3),3), Result=c(1:1)) DF$Date = as.Date(DF$Date , "%m-%d-%Y") DT = data.table(DF) DT Cat Date Condition Data1 Data2 Result 1: A 2013-01-08 TRUE 1 1 1 2: A 2013-01-07 TRUE 2 2 1 3: A 2013-01-04 FALSE 3 3 1 4: B 2013-01-08 FALSE 4 1 1 5: B 2013-01-07 FALSE 5 2 1 6: B 2013-01-04 FALSE 6 3 1 7: C 2013-01-08 FALSE 7 1 1 8: C 2013-01-07 FALSE 8 2 1 9: C 2013-01-04 TRUE 9 3 1 Cat,其中Date必须重新计算:

Result

但是,我不知道如何计算这些行的新 setkey(DT, Condition, Cat, Date) DT[J(TRUE), max(Date), by=Cat] Cat V1 1: A 2013-01-08 2: C 2013-01-04 。 在此简化示例中,新Result应为Result

修改
受到eddi回答的启发,我想出了两个可能的解决方案:

使用Data1+Data2的方法:

.I

使用 DT[DT[Condition==TRUE , .I[which.max(Date)], by=Cat][[2]], Result:=Data1+Data2] 的方法(参见eddi的注意事项):

.SD

对于速度/效率,是否有任何建议可供选择?

1 个答案:

答案 0 :(得分:1)

这样的事情会起作用:

dt = data.table(DF)
max_dates = dt[Condition == TRUE,
               list(Date = max(Date), Condition = TRUE),
               by = Cat]

setkey(dt, Cat, Date, Condition)
dt[max_dates, Result := Data1 + Data2]
dt
#   Cat       Date Condition Data1 Data2 Result
#1:   A 2013-01-04     FALSE     3     3      1
#2:   A 2013-01-07      TRUE     2     2      1
#3:   A 2013-01-08      TRUE     1     1      2
#4:   B 2013-01-04     FALSE     6     3      1
#5:   B 2013-01-07     FALSE     5     2      1
#6:   B 2013-01-08     FALSE     4     1      1
#7:   C 2013-01-04      TRUE     9     3     12
#8:   C 2013-01-07     FALSE     8     2      1
#9:   C 2013-01-08     FALSE     7     1      1

警告提示:以上内容依赖于max_dates没有密钥 - 如果您将其更改为拥有密钥(例如,如果您执行了by如果是键的一部分,那么你必须要删除它的键,或者让它在代码中使用与dt相同的键才能使合并正常工作。

这是另一种方法:

dt = data.table(DF)

dt[, Result := Result + (Data1 + Data2 - Result) * Condition * (Date == max(Date)),
     by = list(Cat, Condition)]
# I could've used ifelse here instead, but ifelse is slow