R data.table变换与行爆炸

时间:2014-05-11 16:27:30

标签: r data.table

列之一的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}}多行)以适应下一个时期。感谢

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