我希望深入了解的问题是关于在时间上倒退的非重叠定期周期中计算 R 中的总计和小计。
生成此示例数据框,
library(lubridate)
set.seed(1)
dates <- ymd(today() - days(0:199))
colors <- c('red', 'blue')
sample_colors <- sample(colors, 200, replace = TRUE)
objects <- c('pen', 'marker', 'brush')
sample_objects <- sample(objects, 200, replace = TRUE)
test_df <- data.frame(dates, sample_colors, sample_objects)
我最终得到了这样的结果:
> head(test_df)
dates sample_colors sample_objects
1 2023-08-14 red pen
2 2023-08-15 red marker
3 2023-08-16 blue pen
4 2023-08-17 red pen
5 2023-08-18 blue pen
6 2023-08-19 blue brush
假设我想每 60 天倒数一次最不常见的颜色对象分组的数量(例如蓝色画笔、红色笔等)。我将开始,无需向后退并转向
slider
包。我会继续
period_count <- function(data) {
summarise(data,
earliest_day_of_period = min(floor_date(dates, "day")),
latest_day_of_period = max(floor_date(dates, "day")),
sub_total = n(),
.by = c(sample_colors, sample_objects)
) %>%
summarise(
earliest_day_of_period = first(earliest_day_of_period),
latest_day_of_period = first(latest_day_of_period),
day_span = first(latest_day_of_period) - first(earliest_day_of_period),
min_object_n = min(sub_total)
)
}
test_df <- test_df %>% arrange(dates)
test_df_period_counts <- slide_period_dfr(.x = test_df,
.i = test_df$dates,
.period = "day",
.f = period_count,
.every = 60,
.complete = TRUE
)
(顺便说一句,我知道
across()
已被弃用,因此对过时的用法表示歉意。只是还没有体验 reframe()
语法。)
slide_period_dfr
操作让我得到了这个,
> test_df_period_counts
earliest_day_of_period latest_day_of_period day_span min_object_n
1 2023-08-14 2023-09-15 32 days 4
2 2023-09-20 2023-11-10 51 days 6
3 2023-11-19 2024-01-10 52 days 4
4 2024-01-18 2024-02-24 37 days 6
这让我很困惑,因为没有出现 60 天长的经期,而且有两个较短的部分经期在中间较长的经期后面。也许我获取每个周期的第一天和最后一天的方式不正确。
但是,假设上面提供的日期是正确的,我想要做的是从最后一天向后开始完整的周期形成,使得部分周期/窗口位于开始而不是结束。我想要一个从
"2024-02-29"
向后推算的完整 60 天周期,依此类推,直到不再可能存在完整周期,然后应将其丢弃。另外,即使我已将 .complete
中的 slide_period_dfr
参数设置为 TRUE
,操作仍在部分大小的周期上发生(这是全部!)。如果有人可以让我知道我做错了什么来迫使这些部分窗口仍然进行计算,请告诉我。
因此,总而言之,是否可以使用
slider
包向后进行精确的周期创建,或者我需要使用不同的包和实现方法?谢谢您的帮助。
我认为这里发生了两件事:
every
值是 u2060> 1u2060period_count()
函数有一些错误。如果您在计算整个期间的日期跨度时group_by(sample_colors, sample_objects)
,您将为每个组获得不同的日期,并且该期间的表观长度将根据出现次数最少的对象的最小和最大日期计算,而不是根据期间的所有对象。但是我们可以稍微简化
period_count()
函数:
period_count <- function(dat) {
dat |>
add_count(sample_colors, sample_objects, name = "sub_total") |>
summarise(
earliest_day_of_period = min(dates),
latest_day_of_period = max(dates),
day_span = latest_day_of_period - earliest_day_of_period,
min_object_n = min(sub_total)
)
}
与提供
.origin
一起,这会产生从末尾开始的非重叠周期:
slider::slide_period_dfr(
test_df,
.i = test_df$dates,
.period = "day",
.f = period_count,
.every = 60,
.complete = TRUE,
.origin = max(test_df$dates) +1
)
# earliest_day_of_period latest_day_of_period day_span min_object_n
# 1 2023-08-15 2023-09-03 19 days 1
# 2 2023-09-04 2023-11-02 59 days 5
# 3 2023-11-03 2024-01-01 59 days 6
# 4 2024-01-02 2024-03-01 59 days 6