Удаление дубликатов записей на основе количества NA

#r #filter #group-by #duplicates

#r #Фильтр #группировать по #дубликаты

Вопрос:

У меня есть набор данных с первичным ключом, называемым ID. Первичный ключ дублируется в нескольких строках. Повторяющиеся строки содержат разное количество отсутствующей информации, представленной в виде NA.

Я хочу сгруппировать по идентификатору первичного ключа, затем сохранить запись, содержащую наибольшее количество информации и наименьшее количество NA.

Я получил приведенный ниже код, чтобы получить мне grouped_by для дубликатов, но я изо всех сил пытаюсь удалить строки с наибольшим количеством NA.

С приведенными ниже данными я хотел бы сохранить первую строку, а вторую и третью удалить, потому что в них отсутствует больше значений, чем в первой строке.

В строке 1 отсутствует только 1 значение, и ее следует сохранить, в то время как в строках 2-3 отсутствуют 2 и 3 значения соответственно.

 dupes = df %>%
  group_by(ID) %>%
  filter(n()>1)

ID   Product   Cost   Date   Name    State
1      X       NA     2019   John    CA
1      NA      15     NA     Bill    GA
1      NA      NA     2019   NA      CA
2      Y       15     2019   Chris   CA
  

Комментарии:

1. Не так ли df%>% filter(!is.na(Product))

2. Справедливое замечание, но нет. Я отредактирую сообщение, чтобы проиллюстрировать, но набор данных состоит из 30 столбцов с большим количеством комбинаций отсутствующих значений. Фильтрация по NA в одном столбце этого не сделает.

3. Допустим, у вас количество NA равно 10 15 20 (среди 30 столбцов) для идентификатора 1, какой из них вы бы сохранили

4. Я бы хотел сохранить 10, удалить 15 и 20.

5. Попробуйте df %>% mutate(n = rowSums(is.na(.))) %>% group_by(ID) %>% slice(which.min(n))

Ответ №1:

Одним из вариантов было бы создать условие, основанное на количестве NA s в каждой строке, т.е. после группировки по ‘ID’, slice строк, содержащих минимальное количество NA элементов

 library(dplyr)
df %>%
   mutate(n = rowSums(is.na(.))) %>% 
   group_by(ID) %>% 
   slice(which.min(n)) %>% 
   select(-n)
  

Или аналогичная логика с data.table

 library(data.table)
setDT(df)[df[, .I[which.min(Reduce(` `, lapply(.SD, is.na)))], ID]$V1]
  

Комментарии:

1. Это сделало свое дело. рекомендация акруна кажется очень похожей на использование slice, но это заняло намного больше времени. Ваша работала намного быстрее. Большое вам спасибо за помощь!