考虑以下示例:
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])
然而,我发现这是不必要的复杂,而且在大型数据集中,从长到宽可能需要相当长的时间,所以我认为必须有更好的方法来做到这一点
如果您想将数据保持为长格式,一种方法是按每个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
带有data.table
的选项
library(data.table)
library(zoo)
setDT(df)[, .(diff = -diff(expenditure)), .(client_id, month_date = as.yearmon(date))]