2016-04-29 3 views
2

Я хочу проверить, какие строки матрицы или dataframe дублируются, как мы можем ее найти?Удалить повторяющиеся строки матрицы или dataframe

Мы хотим удалить повторяющиеся строки. Дублирующиеся строки - это строки, которые имеют одинаковые значения в обоих столбцах 1 и 2, игнорируя их порядок.

Например, для следующей матрицы:

Col1 Col2  database 
A  B  IntAct 
A  B  Bind 
B  A  BioGrid 

Я хочу иметь только одну из строк.

Col1 Col2  database 
A  B  IntAct 

ответ

3
d[!(duplicated(d[,1:2]) | rev(duplicated(d[rev(rownames(d)), 1:2]))),] 
    Col1 Col2 database 
1 A B IntAct 

duplicated показывает строки, которые соответствуют один с более низким индексом. Этого недостаточно, но применяя его в кадре данных, как сверху вниз, так и снизу-вверх дает то, что вы хотите.

+0

Когда я добавляю новую строку в матрицу, она не работает. Я задаю этот вопрос для общего случая, и матрица выборки дается только для лучшего понимания. – Zaynab

+0

Вы правы. У меня была ошибка, теперь исправленная. –

+1

Извините, это не работает! Мне нужно рассматривать строки с одинаковой парой значений в столбцах 1 и 2 (без учета их порядков в столбцах) как дублированные столбцы. (A, B) и (B, A) дублируются. Это условие должно выполняться для всех строк. – Zaynab

3

Вставить столбцы вместе с сепаратором, а затем использовать дублируются:

df[ !duplicated(apply(df[, 1:2], 1, function(i)paste(sort(i), collapse = ","))), ] 
+0

Кажется, хорошо, Большое вам спасибо. – Zaynab

+1

@ Zaynab Почему «кажется»? Это либо работает, либо нет. Сообщите нам, если он не работает с вашими реальными данными. Он работает, например, на вашем сообщении. – zx8754

+2

@ zx8754 Я думаю, вы можете заменить 'paste (... collapse = ..)' part с 't()': 'df [! Duplicated (t (apply (df [, 1: 2], 1, sort))),] ' – RHertel

5

Вот еще один вариант использования pmax/pmin

library(data.table) 
setDT(df1)[!duplicated(pmin(Col1, Col2), pmax(Col1, Col2))] 
# Col1 Col2 database 
#1: A B IntAct 

бенчмаркинг с большим данных:

# dummy data 
set.seed(123) 
df <- data.frame(Col1 = sample(c("A", "B", "C"), 1000, replace = TRUE), 
       Col2 = sample(c("A", "B", "C"), 1000, replace = TRUE), 
       database = sample(c("IntAct", "Bind", "BioGrid"), 1000, 
            replace = TRUE), stringsAsFactors = FALSE) 
# benchmark 
microbenchmark::microbenchmark(
    t = df[ !duplicated(t(apply(df[, 1:2], 1, sort))), ] , 
    paste = df[ !duplicated(apply(df[, 1:2], 1, 
           function(i)paste(sort(i), collapse = ","))), ], 
    pmin = df[ !duplicated(cbind(pmin(df[, 1], df[, 2]), pmax(df[, 1], df[, 2]))), ], 
    times = 1000) 

# Unit: milliseconds 
# expr  min  lq  mean median  uq  max neval cld 
#  t 33.49008 36.337253 38.374825 37.420015 39.610627 153.89251 1000 b 
# paste 33.24177 36.102055 38.079015 37.330498 39.465803 151.43734 1000 b 
# pmin 2.59116 2.790864 3.034999 2.910316 3.137389 11.99905 1000 a 
4

многословными альтернативным использованием sqldf:

Первая строка
Мы создаем столбец идентификатора, чтобы получить первое сообщение.

library(sqldf) 
df$id <- seq.int(nrow(df)) 
sqldf("select col1, col2, database, min(id) id 
     from (select col1, col2, database, id from df where col1 <= col2 
     union all 
     select col2 col1, col1 col2, database, id from df where col1 > col2) 
     group by col1, col2") 

Выход:

col1 col2 database id 
1 A B IntAct 1 

Последняя строка (третий в этом примере)
Более кратким вариант, предложенный Г. Гротендиком

sqldf("select col1, col2, database 
     from (select col1, col2, database from df where col1 <= col2 
     union all 
     select col2 col1, col1 col2, database from df where col1 > col2) 
     group by col1, col2") 

Выход:

col1 col2 database 
1 A B BioGrid 
+0

Ничего против' sqldf', но я думаю, что для этого случая это немного перебор. – zx8754

+1

@ zx8754 Согласен. Я просто сделал это ради ссылки, возможно, полезен для тех, кто приходит с SQL. – mpalanco

+1

В sqlite можно было избежать определения столбца id.Это немного короче: 'library (sqldf); sqldf ("select col1, col2, database from (выберите col1, col2, database from df где col1 <= col2 union all выберите col2 col1, col1 col2, база данных из df, где col1> col2) группа по col1, col2 ")' –

Смежные вопросы