Как мутировать переменные во временном окне роллвинга группами с неравными временными расстояниями?

У меня есть большой df с примерно 40 000 000 строк, охватывающий в общей сложности период времени в 2 года и более 400 тысяч уникальных пользователей. Переменная времени имеет формат POSIXct, и у меня есть уникальный user_id для каждого пользователя. Я наблюдаю за каждым пользователем в течение нескольких моментов времени.

Таким образом, каждая строка представляет собой уникальную комбинацию user_id, времени и набора переменных.

Основываясь на наборе фиктивных переменных (df$v1, df$v2), переменной категории (df$category_var) и переменной времени (df$time_var), теперь я хочу вычислить 3 новые переменные на уровне user_id на скользящее временное окно за предыдущие 30 дней. Таким образом, в каждой строке новая переменная должна быть рассчитана по значениям входных переменных за предыдущие 30 дней.

Я не наблюдаю за всеми пользователями за один и тот же период времени, некоторые заходят позже, некоторые уходят раньше, также расстояния между временами не равны, поэтому я не могу вычислить переменные только по количеству строк.

До сих пор мне удалось рассчитать только мои новые переменные для каждого user_id за весь период наблюдения, но я не смог рассчитать переменные для предыдущих 30-дневных скользящих окон для каждого пользователя.

Проверив и попробовав все связанные сообщения здесь, я предполагаю, что решение data.table является наиболее подходящим, но, поскольку до сих пор я в основном работал с dplyr, попытка вычисления этих переменных в окне скользящего времени на уровне groupey_by user_id заняла больше недели безрезультатно. Буду очень признателен за вашу поддержку!

Мой df в основном выглядит так:

user_id <- c(1,1,1,1,1,2,2,2,2,3,3,3,3,3)
time_var <- c(“,2,3,4,5, 1.5, 2, 3, 4.5, 1,2.5,3,4,5)
category_var <- c(“A”, “A”, “B”, “B”, “A”, “A”, “C”, “C”, “A”, …)
v1 <- c(0,1,0,0,1,0,1,1,1,0,1,…)
v2 <- c(1,1,0,1,0,1,1,0,...)

  1. Моя первая необходимая новая переменная (new_x1) в основном представляет собой кумулятивную сумму, основанную на условии в фиктивной переменной v1. Что я достиг до сих пор:

df <- df %>%  group_by(user_id) %>% mutate(new_x1=cumsum(v1==1)) 

Что мне нужно: эти переменные учитывают только предыдущие 30 дней для каждого пользователя.

  1. Нужна новая переменная (new_x2): в основном кумулятивный счетчик v1, если v2 имеет (пока что) уникальное значение. Таким образом, для каждого нового значения в v2 с учетом v1==1 подсчитывается.

Что я достиг до сих пор:

df <- df %>% 
group_by(user_id, category_var) %>%
 mutate(new_x2 = cumsum(!duplicated(v2 )& v1==1))

Мне также нужно это на основе предыдущих 30 дней, а не всего периода наблюдения за пользователем.

  1. Моя третья интересующая переменная (new__x3): время между двумя наблюдениями при определенном условии (v1==1)
#Interevent Time 
df2 <- df%>% group_by(user_id) %>% filter(v1==1) %>% mutate(time_between_events=time-lag(time))


Мне также понадобится это в предыдущие 30 дней.

Большое спасибо!

Редактировать после поста Джона Спрингса:

Тогда моим потенциальным решением будет

setDT(df)[, `:=`(new_x1= cumsum(df$v1==1[df$user_id == user_id][between(df$time[df$user_id == user_id], time-30, time, incbounds = TRUE)]), 
                         new_x2= cumsum(!duplicated(df$v1==1[df$user_id == user_id][between(df$time[df$user_id == user_id], time-30, time, incbounds = TRUE)]))),
                  by = eval(c("user_id", "time"))]

Я действительно не знаком с data.table и не уверен, смогу ли я вложить свои условия в cumsum в data.table вот так.

Какие-либо предложения?


person ReLa    schedule 23.04.2019    source источник
comment
Рассчитали ли вы разницу во времени между посещениями каждого пользователя? вы можете сделать это с помощью group_by (user_id) %›% организовать (дата) %›% mutate (daysbetween = as.integer (difftime (дата, отставание (дата), единицы = дни)) %›% ungroup(). Вы можете затем суммировать по строкам в этом столбце и фильтровать по строкам ‹30?   -  person hisspott    schedule 24.04.2019
comment
Я ожидаю, что для такого количества отдельных групп data.table будет намного быстрее и четче, чем dplyr. Я не знаю решения dplyr, которое не было бы громоздким для такого большого количества данных. Для меньших данных вы можете использовать padr::pad, чтобы заполнить все дни, а затем использовать общую сумму и отставание, чтобы получить среднее значение за 30 дней. stackoverflow.com/ вопросы/41719929/   -  person Jon Spring    schedule 24.04.2019
comment
@hisspott: Разве тогда мне не нужно время разности каждой строки с каждой предыдущей другой строкой в ​​наборе данных не только между двумя последовательными строками? Я хочу рассчитать все строки за предыдущие 30 дней.   -  person ReLa    schedule 24.04.2019
comment
@Jon Spring Спасибо, Джон. Итак, я (все еще) пока действительно не знаком с data.table, но я вижу здесь необходимость. Я опубликую предлагаемое решение.   -  person ReLa    schedule 24.04.2019