Фильтрация дублированных/неповторных строк в data.table
У меня есть таблица data.table
с примерно 2,5 миллионами строк. Есть два столбца. Я хочу удалить любые строки, которые дублируются в обоих столбцах. Раньше для data.frame я бы сделал следующее:
df -> unique(df[,c('V1', 'V2')])
, но это не работает с data.table. Я пробовал unique(df[,c(V1,V2), with=FALSE])
, но, похоже, все еще работает только с ключом data.table, а не со всей строкой.
Любые предложения?
Cheers,
Дэви
Пример
>dt
V1 V2
[1,] A B
[2,] A C
[3,] A D
[4,] A B
[5,] B A
[6,] C D
[7,] C D
[8,] E F
[9,] G G
[10,] A B
в приведенной выше таблице данных. где V2
- это ключ таблицы, будут удалены только строки 4,7 и 10.
> dput(dt)
structure(list(V1 = c("B", "A", "A", "A", "A", "A", "C", "C",
"E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F",
"G")), .Names = c("V1", "V2"), row.names = c(NA, -10L), class = c("data.table",
"data.frame"), .internal.selfref = <pointer: 0x7fb4c4804578>, sorted = "V2")
Ответы
Ответ 1
До v1.9.8
Из ?unique.data.table
ясно, что вызов unique
для таблицы данных работает только для ключа. Это означает, что вы должны сбросить ключ для всех столбцов перед вызовом unique
.
library(data.table)
dt <- data.table(
V1=LETTERS[c(1,1,1,1,2,3,3,5,7,1)],
V2=LETTERS[c(2,3,4,2,1,4,4,6,7,2)]
)
Вызов unique
с одним столбцом в качестве ключа:
setkey(dt, "V2")
unique(dt)
V1 V2
[1,] B A
[2,] A B
[3,] A C
[4,] A D
[5,] E F
[6,] G G
Для v1.9. 8+
From ?unique.data.table
По умолчанию используются все столбцы (что согласуется с ?unique.data.frame
)
unique(dt)
V1 V2
1: A B
2: A C
3: A D
4: B A
5: C D
6: E F
7: G G
Или используя аргумент by
, чтобы получить уникальные комбинации определенных столбцов (как ранее использовались ключи)
unique(dt, by = "V2")
V1 V2
1: A B
2: A C
3: A D
4: B A
5: E F
6: G G
Ответ 2
С вашим примером data.table...
> dt<-data.table(V1 = c("B", "A", "A", "A", "A", "A", "C", "C", "E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F", "G"))
> setkey(dt,V2)
Рассмотрим следующие тесты:
> haskey(dt) # obviously dt has a key, since we just set it
[1] TRUE
> haskey(dt[,list(V1,V2)]) # ... but this is treated like a "new" table, and does not have a key
[1] FALSE
> haskey(dt[,.SD]) # note that this still has a key
[1] TRUE
Итак, вы можете перечислить столбцы таблицы, а затем взять unique()
из этого, без необходимости устанавливать ключ ко всем столбцам или отбрасывать его (путем установки его на NULL
), как того требует решение от @Andrie (и отредактировано @MatthewDowle). Решения, предложенные @Pop и @Rahul, не сработали для меня.
См. пример 3, который очень похож на вашу первоначальную попытку. Ваш пример не был ясен, поэтому я не уверен, почему он не работает. Также было несколько месяцев назад, когда вы разместили вопрос, так что, возможно, data.table
был обновлен?
> unique(dt) # Try 1: wrong answer (missing V1=C and V2=D)
V1 V2
1: B A
2: A B
3: A C
4: A D
5: E F
6: G G
> dt[!duplicated(dt)] # Try 2: wrong answer (missing V1=C and V2=D)
V1 V2
1: B A
2: A B
3: A C
4: A D
5: E F
6: G G
> unique(dt[,list(V1,V2)]) # Try 3: correct answer; does not require modifying key
V1 V2
1: B A
2: A B
3: A C
4: A D
5: C D
6: E F
7: G G
> setkey(dt,NULL)
> unique(dt) # Try 4: correct answer; requires key to be removed
V1 V2
1: B A
2: A B
3: A C
4: A D
5: C D
6: E F
7: G G
Ответ 3
unique(df)
работает на вашем примере.
Ответ 4
Это должно работать для вас
dt <- unique(dt, by = c('V1, 'V2'))