如何有效地找到R data.table中具有非零值的最后前一行

ira*_*ira 6 r data.table

介绍

我试图找到一种最佳方法,如何找到给定列中最后一个非零值的行,并在该行上返回不同列的值。我想在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))
Run Code Online (Sandbox Code Playgroud)

这提供给我们以下数据表:

    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
Run Code Online (Sandbox Code Playgroud)

现在,该表适用于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']
Run Code Online (Sandbox Code Playgroud)

问题

我可以使示例中的代码更有效吗?

Mic*_*ico 5

您可以尝试使用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
Run Code Online (Sandbox Code Playgroud)

目前,这nafill是仅开发功能(data.table1.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]
Run Code Online (Sandbox Code Playgroud)

这将是低效率的,因为它z==0是按组重复计算的(而不是作为单个向量);您可以在第一步中执行以下操作:

DT[ , z_zero := z == 0]
Run Code Online (Sandbox Code Playgroud)

但这种装置的另一个伪柱(用更少的存储比y_copy如果ynumericcharacter,或complex

  • 或者使用gitlab repo url从二进制文件安装,因此不需要Rtools在Windows上安装 (3认同)

chi*_*n12 3

使用滚动连接的另一个选项:

DT[, output:= DT[z==1][.SD, on=.(x, y), roll=Inf, x.y]]
Run Code Online (Sandbox Code Playgroud)

输出:

    x y z output
 1: b 1 0     NA
 2: b 2 1      2
 3: b 3 0      2
 4: b 4 1      4
 5: b 5 1      5
 6: b 6 0      5
 7: a 1 0     NA
 8: a 2 1      2
 9: a 3 0      2
10: a 4 0      2
11: a 5 1      5
12: a 6 0      5
13: c 1 0     NA
14: c 2 0     NA
15: c 3 0     NA
16: c 4 1      4
17: c 5 0      4
18: c 6 0      4
Run Code Online (Sandbox Code Playgroud)