当列之一的cumsum打破期间时,我想将一行拆分为两行(或更多行)。 有没有优雅的方法来使用data.table执行这样的特定行爆炸? 不要专注于cumsum(我以相反的顺序使用从最近一行到最旧的一行的cumsum),严格来说我想从下面的代码将 dt 转换为 rdt
# current data
dt <- data.table(
time_id = 101:110,
desc = c('asd','qwe','xyz','qwe','qwe','xyz','asd','asd','qwe','asd'),
value = c(5.5,3.5,14,0.7,6,5.5,9.3,29.8,4,7.2)
)
dt[, cum_value_from_now := rev(cumsum(rev(value)))]
period_width <- 10
dt[, value_period := ceiling(cum_value_from_now/period_width)*period_width]
dt
# expected result
rdt <- data.table(
time_id = c(101,102,103,103,104,105,105,106,107,107,108,108,108,108,109,109,110),
desc = c('asd','qwe','xyz','xyz','qwe','qwe','qwe','xyz','asd','asd','asd','asd','asd','asd','qwe','qwe','asd'),
value = c(5.5,3.5,6.5,7.5,0.7,1.8,4.2,5.5,0.3,9,1,10,10,8.8,1.2,2.8,7.2)
)[, cum_value_from_now := rev(cumsum(rev(value)))][, value_period := ceiling(cum_value_from_now/period_width)*period_width]
rdt
# validation
all.equal(
dt[,list(time_id,desc,value)],
rdt[,list(value = sum(value)), by=c('time_id','desc')]
)
编辑我意识到我的问题没有得到解释,我想要执行的转换。为了更好地理解打破时间的含义,请查看我的rdt
从最后到第一个的cum_value_from_now
值。每个value_period
完全由cumsum
上的value
填充,value
的其余部分作为新行生成(如果value
足够大则生成为{{1}}多行)以适应下一个时期。感谢
答案 0 :(得分:1)
首先,您似乎不一致地应用您的规则。如果&#34;打破时期&#34;意味着一行与前一行有value_period
不同,然后第二行打破了这段时间,但你没有这样对待它。
其次,你永远不会解释价值的划分。例如,第3行有value=14
。这在rdt
中被替换为两行,值为6.5和7.5。这些都可以增加到14,但是没有解释为什么这应该是6.5和7.5,而不是说7和7.所以在下面的解决方案中我平均分配。
下面的代码会生成一个通过测试的结果,但由于上述问题存在问题,因此与rdt
不完全相同。
dt[,diff:=c(-diff(value_period)/10,0)]
rdt <- dt[,list(value=as.numeric(rep(value/(diff+1),diff+1))),
by=list(time_id,desc,cum_value_from_now, value_period)]
all.equal(
dt[,list(time_id,desc,value)],
rdt[,list(value = sum(value)), by=c('time_id','desc')]
)
# [1] TRUE