删除 data.table 中每组的尾随值

Removing trailing values per group in data.table

我想删除在 data.table 中等于零的所有最后分组观察值(下面示例中的 Value 列)。我想保留中间 0 值。感谢任何帮助。

library(data.table)

df <- structure(list(Country = c("NL", "NL", "NL", "NL", "DE", "DE", 
"DE", "GB", "GB"), Value = c(1, 2, 3, 0, 3, 0, 1, 2, 0), Value2 = c(100, 
200, 400, 500, 200, 200, 100, 800, 600)), row.names = c(NA, -9L
), class = c("data.table", "data.frame"))

   Country Value Value2
1:      NL     1    100
2:      NL     2    200
3:      NL     3    400
4:      NL     0    500
5:      DE     3    200
6:      DE     0    200
7:      DE     1    100
8:      GB     2    800
9:      GB     0    600

期望的输出:

   Country Value Value2
1:      NL     1    100
2:      NL     2    200
3:      NL     3    400
4:      DE     3    200
5:      DE     0    200
6:      DE     1    100
7:      GB     2    800

你可以使用-

library(data.table)
df[, .SD[!(Value == 0 & seq_len(.N) == .N)], Country]

#   Country Value Value2
#1:      NL     1    100
#2:      NL     2    200
#3:      NL     3    400
#4:      DE     3    200
#5:      DE     0    200
#6:      DE     1    100
#7:      GB     2    800

不执行任何分组功能,您也可以使用 duplicated

setDT(df)[!(!duplicated(Country, fromLast = TRUE) & Value == 0)]

这可以写成dplyr为-

library(dplyr)

#1. 
df %>%
  group_by(Country) %>%
  filter(!(Value == 0 & row_number()== n())) %>%
  ungroup

#2.
df %>% filter(!(!duplicated(Country, fromLast = TRUE) & Value == 0))

为了完整起见,这里有一个 data.table 解决方案,它使用 last().I:

df[!df[, last(.I[last(Value) == 0]), by = Country]$V1]
   Country Value Value2
1:      NL     1    100
2:      NL     2    200
3:      NL     3    400
4:      DE     3    200
5:      DE     0    200
6:      DE     1    100
7:      GB     2    800

df[, last(.I[last(Value) == 0]), by = Country] returns 索引 .I 到要删除的行的原始数据集 df 中:

   Country V1
1:      NL  4
2:      GB  9

警告

这种方法以及目前发布的其他答案只会删除 一个 尾随零,但不会删除多个尾随零。

删除多个尾随零

如果国家序列末尾有多个尾随零,则可以使用 rle() 函数:

library(data.table)
df2[, {
  r <- rle(Value)
  if (last(r$values) == 0)
    head(.SD, -last(r$lengths))
  else
    .SD
}, Country]
    Country Value Value2
 1:      NL     1    100
 2:      NL     2    200
 3:      NL     3    400
 4:      DE     3    200
 5:      DE     0    200
 6:      DE     1    100
 7:      GB     2    800
 8:      FR     1    100
 9:      FR     0    200
10:      FR     3    300

数据

df2 <- fread("Country Value Value2
NL     1    100
NL     2    200
NL     3    400
NL     0    500
DE     3    200
DE     0    200
DE     1    100
GB     2    800
GB     0    600
FR     1    100
FR     0    200
FR     3    300
FR     0    400
FR     0    500")

请注意 countryFR 有两个尾随零。