#r #frequency
Вопрос:
У меня есть следующие данные, где идентификатор означает физическое лицо, Дата для даты и Куплено для того, совершил ли кто-то покупку (я сделал это в последний раз, чтобы я мог подсчитать случаи):
ID Date Purchased
1 1 2017-01-01 1
2 1 2017-08-03 1
3 1 2017-09-02 1
4 2 2017-09-04 1
5 2 2018-07-12 1
6 2 2018-11-03 1
7 2 2018-12-05 1
8 2 2019-01-01 1
9 3 2018-02-03 1
10 3 2020-02-03 1
11 3 2020-03-01 1
Я хотел бы создать переменную под названием «Частота», которая вычисляет количество раз, когда человек совершал покупку в прошлом году, суммируя все «Купленные» до определенной даты, которую вы видите во фрейме данных.
Так, например, для строки 3 это приведет к «Частоте» 2, так 2017-01-01
2017-08-03
как и то, и другое в течение одного года 2017-09-02
(то есть в интервале 2016-09-02
и 2017-09-01
).
См. Желаемый результат:
ID Date Purchased Frequency
1 1 2017-01-01 1 0
2 1 2017-08-03 1 1
3 1 2017-09-02 1 2
4 2 2017-09-04 1 0
5 2 2018-07-12 1 1
6 2 2018-11-03 1 1
7 2 2018-12-05 1 2
8 2 2019-01-01 1 3
9 3 2018-02-03 1 0
10 3 2020-02-03 1 0
11 3 2020-03-01 1 1
Для воспроизведения кадра данных:
df <- data.frame(ID = c(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3), Date = as.Date(c('2017-01-01', '2017-08-03', '2017-09-02', '2017-09-04', '2018-07-12', '2018-11-03', '2018-12-05', '2019-01-01', '2018-02-03', '2020-02-03', '2020-03-01')), Purchased = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ))
Я искал в stackoverlow, но пока не смог найти ответа, который я мог бы применить к своей ситуации и получить желаемые результаты. Одна из вещей, которую я нашел и попробовал, заключалась в следующем:
df$frequency <-
sapply(df$Date, function(x){
sum(df$Date < x amp; df$Date >= x - 365)
})
Я считаю, что это может дать мне желаемые результаты, если я смогу найти способ включить, что он группируется по идентификатору (таким образом, он суммируется по идентификатору, а не в целом). Конечно, не могу сказать наверняка, так как я не смог это проверить. Мы очень ценим любую помощь.
Ответ №1:
Вот tidyverse
решение :
library(dplyr)
library(purrr)
library(lubridate)
df %>%
group_by(ID) %>%
mutate(Frequency = map_dbl(Date,
~sum(Purchased[between(Date, .x - years(1), .x - 1)]))) %>%
ungroup
# ID Date Purchased Frequency
# <dbl> <date> <dbl> <dbl>
# 1 1 2017-01-01 1 0
# 2 1 2017-08-03 1 1
# 3 1 2017-09-02 1 2
# 4 2 2017-09-04 1 0
# 5 2 2018-07-12 1 1
# 6 2 2018-11-03 1 1
# 7 2 2018-12-05 1 2
# 8 2 2019-01-01 1 3
# 9 3 2018-02-03 1 0
#10 3 2020-02-03 1 0
#11 3 2020-03-01 1 1
Логика кода заключается в том, что для каждого Date
в каждом ID
это sum
Purchased
значение между текущей датой — 1 год и текущей датой — 1 день.
Комментарии:
1. Уважаемый Ронак Шах, могу ли я попросить краткого объяснения механизма вашего кода. Это блестящая идея, но я не могу обмозговать ее и не могу понять, как она обрабатывает итерацию в столбце Даты. Заранее большое вам спасибо.
2. На самом деле, это просто. Для каждого
date
из них суммируетсяPurchased
значение между прошлым годом и текущей датой.
Ответ №2:
Вы можете использовать неэквивалентные соединения с data.table
:
library(data.table)
setDT(df)
df[,c("Date","Before"):=.(as.Date(Date),as.Date(Date)-365)]
df[df,.(ID, Date),on=.(ID=ID, Date>=Before, Date<=Date)][,.N-1,by=.(ID,Date)]
ID Date V1
1: 1 2017-01-01 0
2: 1 2017-08-03 1
3: 1 2017-09-02 2
4: 2 2017-09-04 0
5: 2 2018-07-12 1
6: 2 2018-11-03 1
7: 2 2018-12-05 2
8: 2 2019-01-01 3
9: 3 2018-02-03 0
10: 3 2020-02-03 0
11: 3 2020-03-01 1