如何在R中循环变量过滤tibble并生成多组子集数据框?
按自定义时间段筛选数据框并生成子集
问题背景
现有如下结构的data.frame:
to.csv = structure(list(geography = c("030223131022122122", "030223131220201023", "030223131023121330", "030223131212130201", "030223131202323120", "030223131202033333", "030223131202003223", "030223131200111131", "030223131032003101", "030223131020030220"), xlon = c(-79.403, -79.44008, -79.30138, -79.20937, -79.39201, -79.40987, -79.44008, -79.36592, -79.2588, -79.43047), xlat = c(43.87067, 43.67234, 43.87562, 43.75076, 43.71305, 43.73985, 43.75572, 43.83205, 43.88948, 43.93895), bounds = c("-79.40369,43.87018,-79.40231,43.87117", "-79.44077,43.67184,-79.43939,43.67284", "-79.30206,43.87513,-79.30069,43.87612", "-79.21005,43.75027,-79.20868,43.75126", "-79.39270,43.71256,-79.39133,43.71355", "-79.41055,43.73935,-79.40918,43.74034", "-79.44077,43.75523,-79.43939,43.75622", "-79.36661,43.83155,-79.36523,43.83255", "-79.25949,43.88899,-79.25812,43.88998", "-79.43115,43.93845,-79.42978,43.93944"), start_date = c("2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01", "2021-07-01"), end_date = c("2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31", "2021-07-31"), agg_day_period = c(1L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L), agg_time_period = c(20L, 22L, 20L, 6L, 14L, 22L, 7L, 16L, 21L, 7L), activity_index_total = c(0.018224, 0.020511, 0.070478, 0.054159, 0.037204, 0.036961, 0.046656, 0.415398, 0.017664, 0.029587)), row.names = c(770468L, 955885L, 621962L, 1164473L, 479957L, 588295L, 61790L, 1338380L, 1225032L, 688909L ), class = "data.frame")
需要按自定义时间段(例如wd_1_5 <- c(1:5)、wd_6_9 <- c(6:9))筛选数据框,生成多个子集用于后续转栅格,但尝试的代码未达预期:
wd_1_5 <- c(1:5) wd_6_9 <- c(6:9) time.periods <- c(wd_1_5, wd_6_9) for(i in time.periods){ df = to.csv %>% filter(agg_day_period == 1, agg_time_period %in% i) %>% group_by(geography, bounds) print(unique(df$agg_time_period)) }
问题分析
原代码的核心问题:
time.periods <- c(wd_1_5, wd_6_9)将两个时间段向量合并为单一向量,循环时i是单个数值而非完整时间段组,导致filter仅匹配单个agg_time_period值- 循环内每次覆盖
df,未保留各时间段的子集 group_by后未执行聚合操作(如summarize),分组仅标记数据,未生成有用结果
解决方案
方法一:循环实现(保留子集到列表)
将时间段存入列表,循环遍历每个组,筛选后保存到结果列表:
# 定义时间段列表 time_period_list <- list( wd_1_5 = 1:5, wd_6_9 = 6:9 ) # 初始化空列表存储结果 result_list <- list() # 循环处理每个时间段 for(period_name in names(time_period_list)){ current_period <- time_period_list[[period_name]] # 筛选并按需聚合(示例计算activity均值) subset_df <- to.csv %>% filter(agg_day_period == 1, agg_time_period %in% current_period) %>% group_by(geography, bounds, xlon, xlat) %>% summarize(avg_activity = mean(activity_index_total, na.rm = TRUE), .groups = "drop") # 将子集存入结果列表,用时间段名称作为键 result_list[[period_name]] <- subset_df } # 查看结果 result_list$wd_1_5 result_list$wd_6_9
方法二:高效的tidyverse分组方法
先给每个观测标记所属时间段组,再按组拆分或嵌套,更简洁:
library(dplyr) library(tidyr) library(purrr) # 标记每个观测的时间段组 labeled_df <- to.csv %>% filter(agg_day_period == 1) %>% mutate( period_group = case_when( agg_time_period %in% 1:5 ~ "wd_1_5", agg_time_period %in% 6:9 ~ "wd_6_9", TRUE ~ "other" # 处理不在目标时间段的观测 ) ) # 方法1:按组拆分为数据框列表 split_list <- labeled_df %>% group_split(period_group, .keep = FALSE) %>% setNames(c("other", "wd_1_5", "wd_6_9")) # 根据实际分组顺序调整名称 # 方法2:嵌套数据框,方便后续批量处理(如转栅格) nested_df <- labeled_df %>% group_by(period_group) %>% nest() %>% mutate(raster_data = map(data, function(df) { # 替换为实际转栅格代码,例如: # raster::rasterFromXYZ(df[, c("xlon", "xlat", "activity_index_total")]) df # 示例保留数据框 }))
说明
- 两种方法均能生成对应时间段的子集,列表形式的结果方便后续批量处理(如循环转栅格)
- 聚合步骤(
summarize)可按需调整,若无需聚合可去掉group_by和summarize
内容的提问来源于stack exchange,提问作者Priya Patel
相关产品推荐
相关产品推荐

