Если я правильно понимаю, ОП хочет отбросить те даты, которые находятся на расстоянии менее шести месяцев от начала периода, и начать новый период с первой даты, которая находится на расстоянии более 6 месяцев от начала предыдущего период (отдельно для каждого id
).
Я понятия не имею, как это может быть достигнуто с помощью нерекурсивного скользящего или неэквивалентного соединения, поскольку нет фиксированной сетки дат. Поэтому я считаю, что это требует своего рода рекурсивного подхода. Вот одна из возможностей:
library(data.table)
library(lubridate)
dataIhave[, dates := as.Date(dates)]
dataIhave[, keep := TRUE]
dataIhave[order(id, dates)
, keep := {
start <- dates[1L]
for (i in tail(seq_along(dates), -1L)) {
if (dates[i] < start %m+% months(6)) {
keep[i] <- FALSE
} else {
start <- dates[i]
}
}
keep
}, by = id][]
id dates keep
1: 1 2018-01-01 TRUE
2: 1 2018-03-01 FALSE
3: 1 2018-07-01 TRUE
4: 1 2019-01-01 TRUE
5: 2 2018-01-03 TRUE
6: 2 2018-07-02 FALSE
7: 3 2018-02-01 TRUE
8: 4 2018-02-01 TRUE
Наконец,
dataIhave[(keep), -"keep"]
id dates
1: 1 2018-01-01
2: 1 2018-07-01
3: 1 2019-01-01
4: 2 2018-01-03
5: 3 2018-02-01
6: 4 2018-02-01
2-й контрольный пример
Важнейшим моментом здесь является обнаружение начала нового периода (в пределах каждого id
).
В качестве дополнительного контрольного примера я добавил две даты к id == 1
,
2018-07-01
и 2018-07-02
.
2018-07-01
является дубликатом. Обе даты должны быть удалены, поскольку они лежат в течение второго 6-месячного периода, начиная с 2018-07-01
.
dataIhave <- fread("
id dates
1 2018-01-01
1 2018-03-01
1 2018-07-01
1 2018-07-01
1 2018-07-02
1 2019-01-01
2 2018-01-03
2 2018-07-02
3 2018-02-01
4 2018-02-01")
Действительно, приведенный выше код возвращает тот же вывод, что и в исходном тестовом примере OP.
Удалить строки только в течение первых шести месяцев для каждого id
Если , вопрос интерпретируется только для удаления записей в течение первого 6-месячного периода для каждого id
и сохранения всей даты через 6 месяцев, что может быть достигнуто с помощью
dataIhave[!dataIhave[, .I[dates < dates[1L] %m+% months(6L)][-1L], by = id]$V1]
, который возвращает
id dates
1: 1 2018-01-01
2: 1 2018-07-01
3: 1 2018-07-01
4: 1 2018-07-02
5: 1 2019-01-01
6: 2 2018-01-03
7: 3 2018-02-01
8: 4 2018-02-01
для второго контрольного примера. (Обратите внимание, что это упрощенная версия ответа Jaap .)