使用data.table的duplicated函数去重未达预期,请教问题原因
data.table多列去重失败的原因分析
问题场景
先看第一个data.table对象df:
df <- data.table(id = c(1, 2, 2, 3) , datee = as.Date(c('2022-01-01', '2022-01-02', '2022-01-02', '2022-01-03')) ); df
输出:
id datee 1: 1 2022-01-01 2: 2 2022-01-02 3: 2 2022-01-02 4: 3 2022-01-03
使用df[!duplicated(id, datee)]得到了预期的去重结果:
df[!duplicated(id, datee)]
输出:
id datee 1: 1 2022-01-01 2: 2 2022-01-02 3: 3 2022-01-03
但对第二个data.table对象df_1:
df_1 <- data.table(a = c(1,1,2) , b = c(1,1,3) ); df_1
输出:
a b 1: 1 1 2: 1 1 3: 2 3
用同样的写法df_1[!duplicated(a, b)]却无法去除重复行,结果还是原表:
df_1[!duplicated(a, b)]
输出:
a b 1: 1 1 2: 1 1 3: 2 3
错误原因
你误用了base R的duplicated()函数参数逻辑:
- base R的
duplicated(x, ...)中,第一个参数x是要检查重复的对象(可以是向量、数据框),第二个参数fromLast是布尔值,控制从后往前检查重复。 - 你写的
duplicated(id, datee)实际上是把id向量作为x,datee被强制转换成布尔值(非零日期都为TRUE),作为fromLast参数传入,本质是仅对id列做从后往前的重复检查,而非基于id和datee两列去重。 - 第一个例子看似成功,只是巧合:你的数据中
id重复的行刚好datee也重复,仅基于id去重就得到了符合预期的结果,但这并非同时用两列去重的逻辑。
正确的多列去重方法
针对data.table的多列去重,推荐以下几种写法:
- 使用data.table专属的
unique()函数,指定去重依据列:
unique(df_1, by = c("a", "b"))
输出:
a b 1: 1 1 2: 2 3
- 在
duplicated()中传入指定列组成的对象,再取反:
# 方法2.1:传入列组成的data.table df_1[!duplicated(df_1[, .(a, b)])] # 方法2.2:直接指定by参数(data.table兼容该参数) df_1[!duplicated(df_1, by = c("a", "b"))]
- 使用
.SD指代当前分组的所有列,配合by参数:
df_1[!duplicated(.SD, by = c("a", "b"))]
内容的提问来源于stack exchange,提问作者Sweepy Dodo
相关产品推荐
相关产品推荐

