如何使用dplyr与purrr按分组时间区间筛选数据?
嘿,作为purrr新手,用它来替代apply完成这个分组筛选任务其实很顺手!我们可以结合dplyr的分组能力和purrr的映射函数,再加上lubridate处理时间区间,一步步实现你的需求,代码清晰又易读。
步骤1:加载必备包
首先得把需要的工具包装上并加载:
library(dplyr) library(purrr) library(lubridate) # 专门处理时间和区间的神器
步骤2:预处理时间数据
原始数据里的时间都是字符串,得先转成可操作的时间对象,特别是要和intervals里的UTC时区对齐:
# 处理原始温度数据的时间列 df_clean <- df %>% mutate(Date.Time = mdy_hm(Date.Time, tz = "UTC")) # 把字符串转成带UTC时区的POSIXct # 处理时间区间数据,把区间字符串转成lubridate的interval对象 intervals_clean <- intervals %>% mutate( # 拆分区间字符串为开始和结束时间 start_time = str_extract(full.interval, "^[^--]+") %>% ymd_hms(tz = "UTC"), end_time = str_extract(full.interval, "[^--]+$") %>% ymd_hms(tz = "UTC"), # 创建可直接判断的interval对象 time_interval = interval(start_time, end_time) ) %>% select(Site, time_interval) # 只保留需要的列
步骤3:用purrr+dplyr完成分组筛选
这里有两种直观的写法,都能达到目的:
写法一:用group_map(更简洁的分组映射)
group_map可以直接对分组后的数据集应用自定义函数,非常适合这种按组处理的场景:
new.df <- df_clean %>% inner_join(intervals_clean, by = "Site") %>% # 先把每个站点对应的区间关联起来 group_by(Site) %>% group_map(function(group_data, group_key) { # 筛选当前站点中时间落在对应区间内的记录 group_data %>% filter(Date.Time %within% time_interval) %>% select(Date.Time, TempC, Site) # 保留需要的列 }) %>% bind_rows() # 把所有组的结果合并成一个数据框
写法二:用map2(更直观的双列表映射)
如果你想更清晰地看到purrr的映射逻辑,可以先把数据拆分成列表,再用map2同时遍历站点数据和对应的区间:
# 把温度数据按站点拆分成列表 df_site_list <- df_clean %>% group_split(Site) # 把区间数据按站点整理成对应的区间列表 interval_site_list <- intervals_clean %>% split(.$Site) %>% map(~ .$time_interval) # 提取每个站点对应的interval # 用map2遍历两个列表,筛选符合条件的记录 result_list <- map2(df_site_list, interval_site_list, function(site_data, site_interval) { site_data %>% filter(Date.Time %within% site_interval) %>% select(Date.Time, TempC, Site) }) # 合并所有结果 new.df <- result_list %>% bind_rows()
步骤4:调整输出格式(可选)
如果你希望输出的Date.Time和你给出的示例格式一致(字符串类型),可以再加一步转换:
new.df <- new.df %>% mutate(Date.Time = format(Date.Time, "%m/%d/%Y %H:%M"))
现在运行代码后,new.df就会和你期望的结果完全一致啦!
内容的提问来源于stack exchange,提问作者LAB
相关产品推荐
相关产品推荐

