Удалите первую строку из каждой группы, если вторая строка соответствует условию

Вот образец моего набора данных:

df=data.frame(id=c("9","9","9","5","5","5","4","4","4","4","4","20","20"),
  Date=c("11/29/2018","11/29/2018","11/29/2018","5/25/2018","2/13/2019","2/13/2019","6/7/2018",
    "6/15/2018","6/20/2018","8/17/2018","8/20/2018","12/25/2018","12/25/2018"), 
  Buyer= c("John","John","John","Maria","Maria","Maria","Sandy","Sandy","Sandy","Sandy","Sandy","Paul","Paul"))

Мне нужно рассчитать разницу между датами, которые я уже сделал, и набор данных будет выглядеть так:

| id |    Date    | Buyer | diff |
|----|:----------:|------:|------|
| 9  | 11/29/2018 |  John | NA   |
| 9  | 11/29/2018 |  John | 0    |
| 9  | 11/29/2018 |  John | 0    |
| 5  | 5/25/2018  | Maria | -188 |
| 5  | 2/13/2019  | Maria | 264  |
| 5  | 2/13/2019  | Maria | 0    |
| 4  | 6/7/2018   | Sandy | -251 |
| 4  | 6/15/2018  | Sandy | 8    |
| 4  | 6/20/2018  | Sandy | 5    |
| 4  | 8/17/2018  | Sandy | 58   |
| 4  | 8/20/2018  | Sandy | 3    |
| 20 | 12/25/2018 | Paul  | 127  |
| 20 | 12/25/2018 | Paul  | 0    |

Теперь, если значение второй строки в каждой группе столбца «diff» больше или равно 5, то мне нужно удалить первую строку каждой группы. Например, значение diff 264 больше 5 для покупателя «Мария» с идентификатором «5», поэтому я бы хотел удалить первую строку в этой группе, которая была бы покупателем «Мария» с идентификатором «5», Дата как '25.05.2018', а разница как '-188'

Ниже приведен образец моего кода:

df1=df %>% group_by(Buyer,id) %>%
  mutate(diff = c(NA, diff(Date))) %>%
  filter(!(diff >=5 & row_number() == 1))

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

Мой ожидаемый результат должен выглядеть так:

| id |    Date    | Buyer | diff |
|----|:----------:|------:|------|
| 9  | 11/29/2018 |  John | NA   |
| 9  | 11/29/2018 |  John | 0    |
| 9  | 11/29/2018 |  John | 0    |
| 5  | 2/13/2019  | Maria | 264  |
| 5  | 2/13/2019  | Maria | 0    |
| 4  | 6/15/2018  | Sandy | 8    |
| 4  | 6/20/2018  | Sandy | 5    |
| 4  | 8/17/2018  | Sandy | 58   |
| 4  | 8/20/2018  | Sandy | 3    |
| 20 | 12/25/2018 | Paul  | 127  |
| 20 | 12/25/2018 | Paul  | 0    |

person hk2    schedule 13.09.2019    source источник
comment
Даты в df не совпадают с вашими печатными данными. Также добавьте столбец diff в df. Может быть, назовите его diffs, пока вы занимаетесь этим, чтобы избежать конфликта с diff().   -  person Shree    schedule 13.09.2019
comment
@ Шри, я это исправил. В моем исходном наборе данных не было столбца diff. Позже мне нужно будет создать то, что я указал в коде.   -  person hk2    schedule 13.09.2019
comment
С нашей точки зрения, это просто вводные данные, которые вы уже рассчитали, поэтому вы должны включить их в данные или включить код для их расчета. В любом случае, теперь это не имеет значения. Посмотрите, помогут ли приведенные ниже ответы.   -  person Shree    schedule 13.09.2019


Ответы (2)


Я думаю, вы забыли указать столбец diff в df. Я создал один под названием diffs, чтобы он не конфликтовал с функцией diff(). -

library(dplyr)

df1 %>% 
  group_by(id) %>% 
  mutate(diffs = c(NA, diff(as.Date(Date, format = "%m/%d/%Y")))) %>% 
  filter(
    n() == 1 |         # always keep if only one row in group
    row_number() > 1 | # always keep all row_number() > 1
    diffs[2] < 5       # keep 1st row only if 2nd row diffs < 5
  ) %>% 
  ungroup()

# A tibble: 11 x 4
   id    Date       Buyer diffs
   <chr> <chr>      <chr> <dbl>
 1 9     11/29/2018 John     NA
 2 9     11/29/2018 John      0
 3 9     11/29/2018 John      0
 4 5     2/13/2019  Maria   264
 5 5     2/13/2019  Maria     0
 6 4     6/15/2018  Sandy     8
 7 4     6/20/2018  Sandy     5
 8 4     8/17/2018  Sandy    58
 9 4     8/20/2018  Sandy     3
10 20    12/25/2018 Paul     NA
11 20    12/25/2018 Paul      0

Данные -

Я добавил stringsAsFactors = FALSE

df1 <- data.frame(id=c("9","9","9","5","5","5","4","4","4","4","4","20","20"),
  Date=c("11/29/2018","11/29/2018","11/29/2018","5/25/2018","2/13/2019","2/13/2019","6/7/2018",
    "6/15/2018","6/20/2018","8/17/2018","8/20/2018","12/25/2018","12/25/2018"), 
  Buyer= c("John","John","John","Maria","Maria","Maria","Sandy","Sandy","Sandy","Sandy","Sandy","Paul","Paul")
  , stringsAsFactors = F)
person Shree    schedule 13.09.2019
comment
@Shree Не могли бы вы объяснить мне логику, используемую в вашем коде? - person hk2; 13.09.2019
comment
@ hk2 просто добавил объяснение в виде комментариев к коду. Для визуализации создайте три столбца с одним условием фильтрации в каждом и примените к ним OR. - person Shree; 13.09.2019

Может быть, я переусердствовал, но вот одна идея,

df8 %>% 
 mutate(Date = as.Date(Date, format = '%m/%d/%Y')) %>% 
 mutate(diff = c(NA, diff(Date))) %>% 
 group_by(id) %>% 
 mutate(diff1 = as.integer(diff >= 5) + row_number()) %>% 
 filter(diff1 != 1 | lead(diff1) != 3) %>% 
 select(-diff1)

который дает,

# A tibble: 11 x 4
# Groups:   id [4]
   id    Date       Buyer  diff
   <fct> <date>     <fct> <dbl>
 1 9     2018-11-29 John     NA
 2 9     2018-11-29 John      0
 3 9     2018-11-29 John      0
 4 5     2019-02-13 Maria   264
 5 5     2019-02-13 Maria     0
 6 4     2018-06-15 Sandy     8
 7 4     2018-06-20 Sandy     5
 8 4     2018-08-17 Sandy    58
 9 4     2018-08-20 Sandy     3
10 20    2018-12-25 Paul    127
11 20    2018-12-25 Paul      0
person Sotos    schedule 13.09.2019