#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