Подтвердить что ты не робот

Фильтрация дублированных/неповторных строк в 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")
4b9b3361

Ответ 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'))