使用 data.table 按组删除特定列中具有前导缺失值的行

Pie*_*nte 5 r zoo na data.table

我有一个像这样的 data.table:

DT <- data.table(id = c(rep("a", 3), rep("b", 3)),
                 col1 = c(NA,1,2,NA,3,NA), col2 = c(NA,NA,5,NA,NA,NA))
   id col1 col2
1:  a   NA   NA
2:  a    1   NA
3:  a    2    5
4:  b   NA   NA
5:  b    3   NA
6:  b   NA   NA
Run Code Online (Sandbox Code Playgroud)

对于每个 id,我想使用 删除 'col1' 中带有前导 s 的行。这是我期待的结果:NAzoo::na.trim

   id col1 col2
1:  a    1   NA
2:  a    2    5
3:  b    3   NA
4:  b   NA   NA
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止所尝试过的。这确实删除了NA“col1”中的前导,但它从结果中省略了“col2”:

DT[ , na.trim(col1), by = id]
   id V1
1:  a  1
2:  a  2
3:  b  3
Run Code Online (Sandbox Code Playgroud)

这也不起作用:

DT[ , .SD[na.trim(col1)], by = id]
   id col1 col2
1:  a   NA   NA
2:  a    1   NA
3:  b   NA   NA
Run Code Online (Sandbox Code Playgroud)

Jaa*_*aap 6

不使用 -package 的可能解决方案zoo

DT[DT[, .I[!!cumsum(!is.na(col1))], by = id]$V1]
Run Code Online (Sandbox Code Playgroud)

你得到:

   id col1 col2
1:  a    1   NA
2:  a    2    5
3:  b    3   NA
4:  b   NA   NA
Run Code Online (Sandbox Code Playgroud)

这是做什么的:

  • 您可以DT[, .I[!!cumsum(!is.na(col1))], id]$V1创建一个要保留的行号向量。通过使用,!!cumsum(!is.na(col1))您可以确保仅省略前导缺失值col1
  • 接下来,您使用该向量对 data.table 进行子集化。
  • !!cumsum(!is.na(col1))与 的作用相同cumsum(!is.na(col1))!=0。使用 将!!所有大于零的数字转换为TRUE并将所有零转换为FALSE
  • .I不一定需要,您还可以使用:DT[DT[, !!cumsum(!is.na(col1)), by = id]$V1]用逻辑向量对 data.table 进行子集化。

cummax@lmo 的评论中有两种替代方案:

# alternative 1:
DT[DT[, !!(cummax(!is.na(col1))), by = id]$V1]

# alternative 2:
DT[as.logical(DT[, cummax(!is.na(col1)), by = id]$V1)]
Run Code Online (Sandbox Code Playgroud)

@jogo 的另一种选择:

DT[, .SD[!!cumsum(!is.na(col1))], by = id]
Run Code Online (Sandbox Code Playgroud)

@Frank 的另一种选择:

DT[, .SD[ rleid(col1) > 1L | !is.na(col1) ], by = id]
Run Code Online (Sandbox Code Playgroud)