Как получить разницу отстающих переменных по дате? - PullRequest
2 голосов
/ 13 апреля 2020

Рассмотрим следующий пример:

library(tidyverse)
library(lubridate)

df = tibble(client_id = rep(1:3, each=24),
            date = rep(seq(ymd("2016-01-01"), (ymd("2016-12-01") + years(1)), by='month'), 3),
            expenditure = runif(72))

В df вы сохранили информацию о ежемесячных расходах от группы клиентов за последние 2 года. Теперь вы хотите рассчитать ежемесячную разницу между этим и предыдущим годом для каждого клиента.

Есть ли способ сделать это, поддерживая "длинный" формат набора данных? Здесь я покажу вам, как я это делаю в настоящее время, что подразумевает широкое распространение:

df2 = df %>% 
  mutate(date2 = paste0('val_',
                        year(date), 
                        formatC(month(date), width=2, flag="0"))) %>% 
  select(client_id, date2, value) %>% 
  pivot_wider(names_from = date2, 
              values_from = value)

df3 = (df2[,2:13] - df2[,14:25])

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

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Опция с data.table

library(data.table)
library(zoo)
setDT(df)[, .(diff = -diff(expenditure)), .(client_id, month_date = as.yearmon(date))]
1 голос
/ 13 апреля 2020

Если вы хотите сохранить данные в длинном формате, можно сгруппировать по месяцам и значениям даты для каждого client_id и рассчитать разницу, используя diff.

library(dplyr)

df %>% 
  group_by(client_id, month_date = format(date, "%m-%d")) %>%
  summarise(diff = -diff(expenditure))

#   client_id month_date  diff
#       <int> <chr>       <dbl>
# 1         1 01-01       0.278  
# 2         1 02-01      -0.0421 
# 3         1 03-01       0.0117 
# 4         1 04-01      -0.0440 
# 5         1 05-01       0.855  
# 6         1 06-01       0.354  
# 7         1 07-01      -0.226  
# 8         1 08-01       0.506  
# 9         1 09-01       0.119  
#10         1 10-01       0.00819
# … with 26 more rows
...