Преимущественное удаление частичных дубликатов в кадре данных - PullRequest
5 голосов
/ 20 мая 2019

При удалении строк, которые являются дубликатами в двух конкретных столбцах, возможно ли предпочтительно сохранить одну из повторяющихся строк на основе третьего столбца?

Рассмотрим следующий пример:

# Example dataframe.
df <- data.frame(col.1 = c(1, 1, 1, 2, 2, 2, 3),
                 col.2 = c(1, 1, 1, 2, 2, 2, 2),
                 col.3 = c('b', 'c', 'a', 'b', 'a', 'b', 'c'))
# Output
col.1 col.2 col.3
    1     1     b
    1     1     c
    1     1     a
    2     2     b
    2     2     a
    2     2     b
    3     2     c

Я хотел бы удалить строки, которые являются дубликатами как в col.1, так и col.2, при этом всегда сохраняя дублирующую строку, имеющую col.3 == 'a', в противном случае не имеет предпочтения для сохраняемой дублирующейся строки.В этом примере результирующий фрейм данных будет выглядеть так:

# Output.
col.1 col.2 col.3
    1     1     a
    2     2     a
    3     2     c

Вся помощь приветствуется!

Ответы [ 5 ]

5 голосов
/ 20 мая 2019

Мы можем сначала заказать на col.3 и удалить дубликаты, т.е.

d1 <- df[with(df, order(col.3)),]
d1[!duplicated(d1[c(1, 2)]),]
#  col.1 col.2 col.3
#3     1     1     a
#5     2     2     a
#7     3     2     c
3 голосов
/ 20 мая 2019

С dplyr вы также можете сделать:

df %>%
 group_by(col.1, col.2) %>%
 filter(col.3 == min(col.3))

  col.1 col.2 col.3
  <dbl> <dbl> <chr>
1     1     1 a    
2     2     2 a    
3     3     2 c 

Или:

df %>%
 group_by(col.1, col.2) %>%
 filter(dense_rank(col.3) == 1)

Или:

df %>%
 group_by(col.1, col.2) %>%
 slice(which.min(match(col.3, letters[1:26])))
3 голосов
/ 20 мая 2019

Так как вы хотите сохранить a, вы можете arrange выбрать один из них и получить 1-й ряд в каждой группе.

library(dplyr)

df %>%
  arrange_all() %>%
  group_by(col.1, col.2) %>%
  slice(1)

#  col.1 col.2 col.3
#  <dbl> <dbl> <fct>
#1     1     1 a    
#2     2     2 a    
#3     3     2 c    

Если значения col.3 не являются последовательными, вы можете arrange вручную ввести их, выполнив

df %>%
  arrange(col.1, col.2, match(col.3, c("a", "b", "c"))) %>%
  group_by(col.1, col.2) %>%
  slice(1)
1 голос
/ 22 мая 2019

вы можете использовать dplyr::distinct, он имеет параметр .keep.all, который позволяет вам сохранить всю первую строку для каждого отдельного набора.Сначала нам нужно отсортировать, чтобы поместить "a" сверху:

library(dplyr)
df %>%
  arrange(col.1, col.2, col.3 != "a") %>%
  distinct(col.1, col.2, .keep_all = TRUE)
#>   col.1 col.2 col.3
#> 1     1     1     a
#> 2     2     2     a
#> 3     3     2     c
1 голос
/ 20 мая 2019

Можно было бы сгруппировать по 'col.1', 'col.2' и slice строке, которая имеет 'col.3' в качестве "a", если количество строк больше 1, или в противном случае возвращаетсяпервая строка

library(dplyr)
df %>% 
   group_by(col.1, col.2) %>%
   slice(if(n() > 1) which(col.3 == 'a') else 1)
# A tibble: 3 x 3
# Groups:   col.1, col.2 [3]
#  col.1 col.2 col.3
#  <dbl> <dbl> <fct>
#1     1     1 a    
#2     2     2 a    
#3     3     2 c    

Или другой вариант - сгруппировать по 'col.1', 'col.2', а затем slice по индексу, который мы получаем из match, используя 'aс «кол.3».если есть nomatch, мы возвращаем индекс 1.

df %>% 
   group_by(col.1, col.2) %>% 
   slice(match("a", col.3, nomatch = 1))
# A tibble: 3 x 3
# Groups:   col.1, col.2 [3]
#  col.1 col.2 col.3
#  <dbl> <dbl> <fct>
#1     1     1 a    
#2     2     2 a    
#3     3     2 c    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...