как удалить строки, которые не полностью дублируются в R

#r #data.table

#r #данные.таблица

Вопрос:

у меня есть пример данных

первый

 resp=structure(list(person_number = c(914198L, 914198L, 914198L, 914198L,  914198L, 957505L, 957505L, 957505L, 957505L, 957505L, 967216L,  967216L, 967216L, 967216L, 967216L, 27771498L, 27771498L, 27771498L,  27771498L, 27771498L, 957505L, 957505L, 957505L, 914198L, 967216L,  967216L, 914198L, 967216L, 914198L), position_code = c(50000690L,  50000690L, 50000690L, 50000690L, 50000690L, 50000690L, 50000690L,  50000690L, 50000690L, 50000690L, 50000690L, 50000690L, 50000690L,  50000690L, 50000690L, 801L, 801L, 801L, 801L, 801L, 50000690L,  50000690L, 50000690L, 50000690L, 50000690L, 50000690L, 50000690L,  50000690L, 50000690L), date = c(7L, 2L, 1L, 4L, 5L, 6L, 3L, 4L,  5L, 2L, 3L, 5L, 1L, 6L, 7L, 7L, 2L, 6L, 4L, 1L, 6L, 3L, 4L, 1L,  3L, 5L, 4L, 7L, 5L), start_hour = c(9L, 9L, 11L, 9L, 9L, 9L,  9L, 11L, 9L, 9L, 9L, 11L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 12L,  15L, 10L, 9L, 11L, 10L, 11L, 10L, 9L), end_hour = c(21L, 21L,  21L, 15L, 15L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L, 21L,  19L, 19L, 19L, 19L, 19L, 21L, 21L, 19L, 21L, 21L, 21L, 21L, 21L,  21L)), class = "data.frame", row.names = c(NA, -29L))  

позвольте мне показать наглядный пример, чтобы вы могли понять, в чем мне нужна помощь. Повторения набора данных и person_number = 957505

 person_number position_code date start_hour end_hour 957505 50000690 6 9 21 957505 50000690 3 9 21 957505 50000690 4 11 21 957505 50000690 5 9 21 957505 50000690 2 9 21 957505 50000690 6 12 21 957505 50000690 3 15 21 957505 50000690 4 10 19  

здесь мы видим, что дата = 6 встречается 2 раза, а диапазон равен from 9-21 and from 12-21 также мы видим, что дата = 4 тоже встречается 2 раза, и диапазон start-end hours 11-21,11-19 это означает, что мне нужно случайным образом удалить наблюдение с повторяющейся датой, но с другим диапазоном. Т. е. мне нужно удалить любое одно наблюдение для даты = 6 и любое для даты = 4

как это

 person_number position_code date start_hour end_hour  957505 50000690 3 9 21 957505 50000690 5 9 21 957505 50000690 2 9 21 957505 50000690 6 12 21 957505 50000690 3 15 21 957505 50000690 4 10 19  

однако бывают и такие случаи

 person_number position_code date start_hour end_hour 957505 50000690 6 9 21 957505 50000690 3 9 21 957505 50000690 4 11 21 957505 50000690 5 9 21 957505 50000690 2 9 21 957505 50000690 6 12 21 957505 50000690 3 15 21 957505 50000690 4 10 19  

мы видим, например, что здесь date = 3 имеет диапазон дубликатов 1 start_hour end_hour from 9-21, and another 15-21 , но диапазон от 15-21 для этого номера персоны больше не дублируется, но 9-21 дублируется более 2 раз для этого номера персоны

 957505 50000690 6 9 21 957505 50000690 3 9 21  957505 50000690 5 9 21 957505 50000690 2 9 21  

это происходит здесь 4 раза, поэтому для даты = 3 мы удаляем 9-21. потому что диапазон от 15-21 не дублируется 2 или более раз. Его нужно оставить. для любых других условий, не указанных, применяется эта часть кодекса здесь мы видим, что дата = 6 встречается 2 раза, и диапазон from 9-21 and from 12-21 также мы видим, что дата = 4 встречается тоже 2 раза, и диапазон start-end hours 11-21,11-19 это означает, что мне нужно случайным образом удалить наблюдение с повторяющейся датой, но с другим диапазоном. Т. е. мне нужно удалить любое одно наблюдение для даты = 6 и любое для даты = 4 Как я могу удалить строки с помощью таких условий? любая помощь будет признательна. Спасибо.

Ответ №1:

Вот идея, как выполнить такую фильтрацию с помощью библиотеки dplyr :

 library(dplyr)  # resp2 will contain all rows with at least double dates multiple_date lt;- resp %gt;% count(person_number, date) %gt;% filter(ngt;1) resp2 lt;- semi_join(resp, multiple_date) # show all of resp2 resp2 # show difference between resp and resp2 anti_join(resp, resp2)  # compare resp with resp2 specifically for person 957505 resp %gt;% filter(person_number == 957505) resp2 %gt;% filter(person_number == 957505)  # resp3 will contain all rows with at least double hour range multiple_hour lt;- resp %gt;% count(person_number, start_hour, end_hour) %gt;% filter(ngt;1)  resp3 lt;- semi_join(resp, multiple_hour)  # compare resp with resp3 specifically for person 957505 resp3 %gt;% filter(person_number == 957505) resp %gt;% filter(person_number == 957505)  # resp4 will contain all rows that have at least double date and at least double hour range resp4 lt;- semi_join(semi_join(resp, resp2), resp3)  # compare resp with resp4 specifically for person 957505 resp4 %gt;% filter(person_number == 957505) resp %gt;% filter(person_number == 957505)  # remove rows that have at least double date and at least double hour range final lt;- anti_join(resp, resp4)  # compare resp with final specifically for person 957505 final %gt;% filter(person_number == 957505) resp %gt;% filter(person_number == 957505)  # check how many entries with double date have been left final %gt;% count(person_number, date) %gt;% filter(ngt;1)  

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

1. — спасибо тебе. # сравните resp с resp2 специально для человека 957505 как сделать для всех людей, а не конкретно . Можете ли вы отредактировать ответ?

2. Просто введите resp2 в командной строке , и вы увидите все данные resp2 , не отфильтрованные для одного человека. Разница между resp2 оригиналом и оригиналом resp была бы anti_join(resp, resp2) . Если данный ответ правильный, пожалуйста, отметьте его как правильный ответ, чтобы другие читатели могли его идентифицировать.

3. я согласился, спасибо. Отлично. Но не понял, можете ли вы отредактировать свой ответ. где тип resp2