如何用循环或apply函数计算指定日期区间内变量的平均值?
自动化计算多日期区间的分组均值(针对dplyr新手)
首先,我先理清楚你的需求:你已经能手动计算单个日期区间的均值,但希望不用每次改日期,自动处理多个区间,而且作为新手不想写复杂的循环。下面给你两种简单易上手的方案,都是基于你已经熟悉的dplyr工具。
先回顾你的手动代码(方便对比)
你之前的手动实现是这样的:
library(dplyr) retailavg <- google.mobility %>% mutate(weekrange = date >= "2020-02-15" & date <= "2020-02-21") %>% filter(weekrange) %>% group_by(sub_region_2) %>% summarise(avgretail = mean(retail_and_recreation_percent_change_from_baseline))
方案1:用purrr实现函数式自动化(新手友好)
purrr是tidyverse家族的工具,比基础循环更直观,代码可读性强,适合新手入门函数式编程。
步骤1:定义所有需要计算的日期区间
先把你要处理的所有日期区间整理成一个列表,每个元素存一个区间的起始和结束日期:
# 先加载需要的包 library(dplyr) library(purrr) # 定义日期区间列表,你可以根据需求添加更多区间 date_ranges <- list( c(start = "2020-02-15", end = "2020-02-21"), c(start = "2020-02-22", end = "2020-02-28"), c(start = "2020-07-21", end = "2020-07-28") # 你举的示例区间 )
步骤2:写一个计算单个区间均值的函数
把你手动写的逻辑封装成函数,输入一个日期区间,输出该区间的分组均值:
calculate_interval_avg <- function(date_range) { # 把字符日期转成日期格式 start_date <- as.Date(date_range["start"]) end_date <- as.Date(date_range["end"]) google.mobility %>% # 过滤当前区间的日期 filter(date >= start_date & date <= end_date) %>% group_by(sub_region_2) %>% summarise( # 计算零售娱乐的均值,加na.rm=TRUE避免缺失值导致结果为NA avg_retail = mean(retail_and_recreation_percent_change_from_baseline, na.rm = TRUE), # 可以顺便计算其他变量的均值,比如杂货店药店 avg_grocery = mean(grocery_and_pharmacy_percent_change_from_baseline, na.rm = TRUE), # 保留区间的起止日期,方便后续区分不同区间的结果 interval_start = start_date, interval_end = end_date ) }
步骤3:批量应用函数到所有区间
用map_dfr函数把上面的函数应用到所有日期区间,结果会自动合并成一个整洁的tibble:
# 自动计算所有区间的均值 all_avg_results <- map_dfr(date_ranges, calculate_interval_avg) # 查看结果 head(all_avg_results)
方案2:基础for循环(适合理解循环逻辑)
如果你想学习基础的循环写法,也可以用for循环实现,逻辑和上面一致:
# 初始化一个空列表,用来存储每个区间的结果 all_results <- list() # 遍历每个日期区间 for (i in seq_along(date_ranges)) { # 取出当前的日期区间 current_range <- date_ranges[[i]] start_date <- as.Date(current_range["start"]) end_date <- as.Date(current_range["end"]) # 计算当前区间的均值 current_result <- google.mobility %>% filter(date >= start_date & date <= end_date) %>% group_by(sub_region_2) %>% summarise( avg_retail = mean(retail_and_recreation_percent_change_from_baseline, na.rm = TRUE), interval_start = start_date, interval_end = end_date ) # 把当前结果加入列表 all_results[[i]] <- current_result } # 把列表里的所有结果合并成一个数据框 all_avg_results <- bind_rows(all_results)
新手额外小贴士
- 自动生成连续周区间:如果你的区间是连续的周(比如每周一个区间),不用手动写每个区间,可以用
seq.Date自动生成:# 生成从2020-02-15开始的4个周起始日期 start_dates <- seq(as.Date("2020-02-15"), by = "week", length.out = 4) # 每个周的结束日期是起始日期+6天(因为包含起始当天) end_dates <- start_dates + 6 # 自动生成日期区间列表 date_ranges <- pmap(list(start_dates, end_dates), ~c(start = .x, end = .y)) - 处理缺失值:一定要加
na.rm = TRUE,否则数据里的缺失值会让均值计算结果变成NA,影响后续分析。 - 扩展多个变量:如果需要计算其他变量(比如公园、工作场所)的均值,直接在
summarise里添加对应的mean()语句即可。
内容的提问来源于stack exchange,提问作者annieblabz
相关产品推荐
相关产品推荐

