У меня есть фрейм данных, который выглядит следующим образом:
require(data.table)
require(tidyverse)
df <- as.data.frame(matrix(c(123, "2018-01-05 09:09:02", "Mobile",
123, "2018-01-06 11:11:15", "Organic",
123, "2018-01-07 13:24:45", "Email",
123, "2018-01-07 13:24:55", "Organic",
321, "2018-01-05 15:15:29", "Organic",
989, "2018-01-08 08:09:21", "Feeds",
989, "2018-01-08 08:09:55", "Organic",
989, "2018-01-10 10:21:40", "Email"), nrow = 8,
ncol = 3, byrow = TRUE, dimnames = list(NULL, c("customer_id", "entry_time",
"channel"))))
df$entry_time <- as.POSIXct(df$entry_time)
df
customer_id entry_time channel
1 123 2018-01-05 09:09:02 Mobile
2 123 2018-01-06 11:11:15 Organic
3 123 2018-01-07 13:24:45 Email
4 123 2018-01-07 13:24:55 Organic
5 321 2018-01-05 15:15:29 Organic
6 989 2018-01-08 08:09:21 Feeds
7 989 2018-01-08 08:09:55 Organic
8 989 2018-01-10 10:21:40 Email
Что я хотел бы сделать, это удалить все «органические» записи, встречающиеся в пятиминутном окне неорганической записи, для каждойcustomer.
Другими словами, я хочу удалить все записи, где: 1) канал = органический и 2) запись_время <5 минут удалено из предыдущей записи и 3) канал предыдущей записи! = органический.Я должен быть в состоянии сделать это для каждого идентификатора клиента. </p>
Мой желаемый результат выглядит следующим образом:
df_desired <- as.data.frame(matrix(c(123, "2018-01-05 09:09:02", "Mobile",
123, "2018-01-06 11:11:15", "Organic",
123, "2018-01-07 13:24:45", "Email",
321, "2018-01-05 15:15:29", "Organic",
989, "2018-01-08 08:09:21", "Feeds",
989, "2018-01-10 10:21:40", "Email"), nrow = 6,
ncol = 3, byrow = TRUE, dimnames = list(NULL, c("customer_id", "entry_time",
"channel"))))
df_desired$entry_time <- as.POSIXct(df_desired$entry_time)
df_desired
customer_id entry_time channel
1 123 2018-01-05 09:09:02 Mobile
2 123 2018-01-06 11:11:15 Organic
3 123 2018-01-07 13:24:45 Email
4 321 2018-01-05 15:15:29 Organic
5 989 2018-01-08 08:09:21 Feeds
6 989 2018-01-10 10:21:40 Email
Я могу сделать это с помощью следующего вложенного цикла (извинения за разоблачениевы это чудовище).
dat_splt <- split(df, df$customer_id)
for (h in 1:length(dat_splt)){
dat_splt[[h]]$prox_flag <- 0
if (nrow(dat_splt[[h]]) == 1)
{next}
else
{for (g in 2:nrow(dat_splt[[h]])){
if (dat_splt[[h]][g,]$channel != "Organic")
{next}
else if (dat_splt[[h]][g-1,]$channel != "Organic" &
as.numeric((difftime(dat_splt[[h]][g,]$entry_time, dat_splt[[h]][g-1,]$entry_time, units = "mins")) < 5))
{dat_splt[[h]][g,]$prox_flag <- 1}
else
{next}
}}
}
dat <- rbindlist(dat_splt)
dat <- dat %>%
filter(prox_flag != 1)
Излишне говорить, что это не хорошо масштабируется.Может кто-нибудь помочь мне распутать этот гордиев узел решения во что-то более практичное?
Большое спасибо заранее.