介绍
我试图找到一种最佳方法,如何找到给定列中最后一个非零值的行,并在该行上返回不同列的值。我想在R data.table中做到这一点,我正在寻找该操作的最大效率。
例
让我们有一个像这样的数据表:
set.seed(123) DT = data.table(x=rep(c("b","a","c"),each=6), y=rep(1:6, 3), z = rbinom(18, 1, 0.3))
这提供给我们以下数据表:
x y z 1: b 1 0 2: b 2 1 3: b 3 0 4: b 4 1 5: b 5 1 6: b 6 0 7: a 1 0 8: a 2 1 9: a 3 0 10: a 4 0 11: a 5 1 12: a 6 0 13: c 1 0 14: c 2 0 15: c 3 0 16: c 4 1 17: c 5 0 18: c 6 0
现在,该表适用于x列中按y列排序的每个值。对于列中的值给出的每个组x
,我想创建一个列,该列为每y
行提供最后一个非零值为的行中的值z
。
现在,我对每个y使用lapply并按x分组,这给出了所需的结果:
DT[, list(y, z, output = lapply(y, function(x) max(y[z != 0 & y <= x])) ), by = 'x']
问题
我可以使示例中的代码更有效吗?
您可以尝试使用nafill
:
# create a dummy column that is only populated for nonzero z (and hence NA elsewhere) DT[z != 0, y_copy := y] # nafill on this column using LOCF strategy by group: DT[ , ans := nafill(y_copy, type = 'locf'), by = x][] # x y z y_copy ans # 1: b 1 0 NA NA # 2: b 2 1 2 2 # 3: b 3 0 NA 2 # 4: b 4 1 4 4 # 5: b 5 1 5 5 # 6: b 6 0 NA 5 # 7: a 1 0 NA NA # 8: a 2 1 2 2 # 9: a 3 0 NA 2 # 10: a 4 0 NA 2 # 11: a 5 1 5 5 # 12: a 6 0 NA 5 # 13: c 1 0 NA NA # 14: c 2 0 NA NA # 15: c 3 0 NA NA # 16: c 4 1 4 4 # 17: c 5 0 NA 4 # 18: c 6 0 NA 4
目前,这nafill
是仅开发功能(data.table
1.12.3+),但下一个或两周内应在CRAN上使用1.12.4。目前,您可以使用install.packages('data.table', type = 'source', repos = 'http://Rdatatable.github.io/data.table')
如果您不想创建y_copy
,则可以通过以下方式内联is.na<-
:
DT[ , ans := nafill(`is.na<-`(y, z == 0), type = 'locf'), by = x]
这将是低效率的,因为它z==0
是按组重复计算的(而不是作为单个向量);您可以在第一步中执行以下操作:
DT[ , z_zero := z == 0]
但这种装置的另一个伪柱(用更少的存储比y_copy
如果y
是numeric
,character
,或complex
)