na.trim在具有data.table的特定列上

时间:2017-05-17 13:04:30

标签: r data.table zoo

我尝试在na.trim对象的单个列上使用包zoo中的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

我想使用na.trim和ID分组删除前导 NAs的行。这是我期待的结果:

   id col1 col2
1:  a    1   NA
2:  a    2    5
3:  b    3   NA
4:  b   NA   NA

这是我到目前为止所尝试的内容。这将删除前导NA但删除col2:

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

这也行不通:

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

2 个答案:

答案 0 :(得分:4)

不使用zoo包的可能解决方案:

DT[DT[, .I[!!cumsum(!is.na(col1))], by = id]$V1]

你得到:

   id col1 col2
1:  a    1   NA
2:  a    2    5
3:  b    3   NA
4:  b   NA   NA

这是做什么的:

  • 使用DT[, .I[!!cumsum(!is.na(col1))], id]$V1创建一个要保留的rownumbers矢量。通过使用!!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进行子集化。

来自评论的@lmo的cummax的两个备选方案:

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

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

@jogo的另一种选择:

DT[, .SD[!!cumsum(!is.na(col1))], by = id]

@Frank的另一种选择:

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

答案 1 :(得分:4)

na.trim将与data.table一样使用。有关其参数的更多信息,请参阅?na.trim

DT[, na.trim(.SD, sides = "left", is.na = "all"), by = id]

,并提供:

   id col1 col2
1:  a    1   NA
2:  a    2    5
3:  b    3   NA
4:  b   NA   NA

增加:

在评论中,海报澄清说,na.trim只应对第1列NAs进行操作。在这种情况下,添加一列行号,.I,并在使用这些行号后使用na.trim子集。

DT[DT[, na.trim(data.table(col1, .I), "left"), by = id]$.I, ]