na.trim 在具有 data.table 的特定列上
na.trim on specific column with data.table
我正在尝试在 data.table
对象的单个列上使用包 zoo
中的 na.trim
。这是我的数据:
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
我想删除具有 leading NA 的行,使用 na.trim
并按 id 分组。这是我期待的结果:
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
不使用 zoo
-package 的可能解决方案:
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
您可以创建一个行号向量来保留。通过使用 !!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]
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 列 NA 进行操作。在那种情况下,附加一列行号,.I,并在使用这些行号涉及 na.trim
子集之后。
DT[DT[, na.trim(data.table(col1, .I), "left"), by = id]$.I, ]
我正在尝试在 data.table
对象的单个列上使用包 zoo
中的 na.trim
。这是我的数据:
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
我想删除具有 leading NA 的行,使用 na.trim
并按 id 分组。这是我期待的结果:
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
不使用 zoo
-package 的可能解决方案:
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
您可以创建一个行号向量来保留。通过使用!!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]
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 列 NA 进行操作。在那种情况下,附加一列行号,.I,并在使用这些行号涉及 na.trim
子集之后。
DT[DT[, na.trim(data.table(col1, .I), "left"), by = id]$.I, ]