Dplyr изменяет данные с начального и конечного уровня на недельный уровень - PullRequest
1 голос
/ 17 июня 2020

У меня есть df, который содержит идентификатор пользователя, дату начала и окончания подписки и, если доступно, дату активности. Пользователи могут появляться более одного раза, если у них несколько дат активности. Ниже приведен небольшой пример игрушки:

USER_ID      SUB_START     SUB_END      ACTIVITY_DATE
  0102       2018-01-02   2018-01-07          NA
  2190       2018-01-01   2018-01-06      2018-01-02
  2432       2018-01-03   2018-01-07      2018-01-03
  0121       2018-01-03   2018-01-04      2018-01-02
  0121       2018-01-02   2018-01-07      2018-01-04

То, что я хотел бы выполнить, sh - это сгруппировать по неделям, а затем показать количество уникальных идентификаторов, которые имели активную подписку на этой неделе, и количество уникальных идентификаторов. на этой неделе был хотя бы 1 день активности. Таким образом, выходные данные для этого набора данных игрушки будут выглядеть так:

 WEEK    ACTIVE_COUNT    ACTIVITY_COUNT
2018-0         4               3

Этот пример упрощен, время между датами SUB_START и SUB_END может быть намного больше. Я пытаюсь подумать, как подойти к этой проблеме. Мне нужно создать столбец WEEK, содержащий каждую неделю от самого маленького format(SUB_START), "%y-%U") до самого большого format(as.Date(SUB_END), "%Y-%U"). Я считаю, что могу выполнить sh с чем-то вроде complete(WEEK = seq.Date(SUB_START, unit = "week"), SUB_END, by = "week")). Однако я не уверен, как я могу затем go в течение каждой недели и подсчитывать количество уникальных идентификаторов, которые были активны в течение этой недели, и подсчитывать количество уникальных активных идентификаторов, у которых был хотя бы один ACTIVITY_DATE в течение этой недели.

РЕДАКТИРОВАТЬ: Используя структуру @ TimTeaFan, я приблизился со следующим кодом:

dat %>% 
                  mutate(across(where(is.character), ~ floor_date(as.Date(.x) - 1, "weeks") + 1)) %>% 
                  rowwise() %>% 
                  mutate(WEEK = list(seq(SUB_START,SUB_END, by = "+1 week"))) %>%
                  unnest(WEEK) %>% 
                  mutate(WEEK2 = format(WEEK, "%Y-%U")) %>% 
                  mutate(ENCOUNTER_WEEK = format(ACTIVITY_DATE, "%Y-%U")) %>%
                  group_by(WEEK2) %>% 
                  mutate(ACTIVE = ifelse(!is.na(ACTIVITY_DATE), ENCOUNTER_WEEK == WEEK2, NA)) %>% 
                  summarise(ACTIVE_COUNT = sum(!is.na(USER_ID)),
                            ACTIVITY_COUNT = sum(ACTIVE, na.rm = TRUE))

Однако это дает общее ACTIVITY_COUNT, а не уникальное количество идентификаторов с активностью на этой неделе

EDIT2: решено ниже

1 Ответ

1 голос
/ 17 июня 2020

Это должно быть то, что вы ищете (обратите внимание, что я изменил данные вашего примера, поскольку все даты начала и окончания были на одной неделе).

library(tidyverse)
library(lubridate)

dat <- tribble(~USER_ID,      ~SUB_START,     ~SUB_END,      ~ACTIVITY_DATE,
               0102,       "2018-01-02",   "2018-01-07",          NA,
               2190,       "2018-01-01",   "2018-03-06",      "2018-01-02",
               2432,       "2018-01-03",   "2018-05-07",      "2018-01-03",
               0121,       "2018-01-03",   "2018-02-04",      "2018-01-02",
               0121,       "2018-01-02",   "2018-01-15",      "2018-01-04")

dat %>% 
  mutate(across(where(is.character), ~ floor_date(as.Date(.x) - 1, "weeks") + 1)) %>% 
  rowwise() %>% 
  mutate(WEEK = list(seq(SUB_START, SUB_END, by = "+1 week"))) %>%
  unnest(WEEK) %>% 
  mutate(WEEK2 = format(WEEK, "%Y-%U")) %>% 
  mutate(ENCOUNTER_WEEK = format(ACTIVITY_DATE, "%Y-%U")) %>%
  group_by(WEEK2, USER_ID) %>% 
  mutate(ACTIVE = ifelse(!is.na(ACTIVITY_DATE), ENCOUNTER_WEEK == WEEK2, NA)) %>% 
  summarise(ACTIVITY_COUNT = sum(ACTIVE, na.rm = TRUE)) %>% 
  summarise(ACTIVE_COUNT = n(),
            ACTIVITY_COUNT = sum(ifelse(ACTIVITY_COUNT > 0, 1, 0)))

#> `summarise()` regrouping output by 'WEEK2' (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 19 x 3
#>    WEEK2   ACTIVE_COUNT ACTIVITY_COUNT
#>    <chr>          <int>          <dbl>
#>  1 2018-00            4              3
#>  2 2018-01            3              0
#>  3 2018-02            3              0
#>  4 2018-03            3              0
#>  5 2018-04            3              0
#>  6 2018-05            2              0
#>  7 2018-06            2              0
#>  8 2018-07            2              0
#>  9 2018-08            2              0
#> 10 2018-09            2              0
#> 11 2018-10            1              0
#> 12 2018-11            1              0
#> 13 2018-12            1              0
#> 14 2018-13            1              0
#> 15 2018-14            1              0
#> 16 2018-15            1              0
#> 17 2018-16            1              0
#> 18 2018-17            1              0
#> 19 2018-18            1              0

Создано 2020-06 -17 с помощью пакета REPEX (v0.3.0)

...