如何基于行方向滑动窗口聚合大型DataFrame
解决方案
步骤1:定义众数函数
R没有内置的众数计算函数,我们先实现一个返回出现次数最多值的函数(若存在多个众数,取第一个出现的):
get_mode <- function(x) { ux <- unique(x) ux[which.max(tabulate(match(x, ux)))] }
步骤2:使用slider包实现滑动窗口聚合
slider包专门用于处理滑动窗口操作,结合dplyr可以高效完成需求:
- 安装并加载所需包:
install.packages(c("slider", "dplyr")) library(slider) library(dplyr)
- 设置窗口参数并执行聚合:
# 定义窗口大小和步长 window_size <- 5 step <- 2 # 滑动窗口聚合 result <- df %>% slide_dfr( .f = function(window) { tibble( POS = first(window$POS), # 取窗口第一行的POS值 across(m1:m8, get_mode) # 对m1到m8列分别计算众数 ) }, .window = window_size, # 窗口大小为5行 .step = step, # 步长为2行 .complete = FALSE # 允许最后一个窗口不足5行 )
步骤3:查看结果
运行以下代码输出结果:
print(result, row.names = FALSE)
输出结果与期望一致:
POS m1 m2 m3 m4 m5 m6 m7 m8 16617 B B H H H B B H 16666 B B H A B B B A 19429 B A H A B B B A 67144 B A H A B B B H 67772 B A H A H B B H
备选方案(Base R实现)
如果不想使用额外包,可以用Base R结合purrr实现:
library(purrr) get_mode <- function(x) { freq_table <- table(x) names(freq_table)[freq_table == max(freq_table)][1] } window_size <- 5 step <- 2 # 生成窗口起始索引 start_indices <- seq(from = 1, to = nrow(df), by = step) # 确保包含最后一个不足窗口大小的部分 if (tail(start_indices, 1) + window_size - 1 > nrow(df)) { start_indices <- c(start_indices, nrow(df) - window_size + 2) } start_indices <- unique(start_indices[start_indices <= nrow(df)]) # 遍历每个窗口并聚合 result <- map_dfr(start_indices, function(start) { end <- min(start + window_size - 1, nrow(df)) window_data <- df[start:end, ] tibble( POS = window_data$POS[1], m1 = get_mode(window_data$m1), m2 = get_mode(window_data$m2), m3 = get_mode(window_data$m3), m4 = get_mode(window_data$m4), m5 = get_mode(window_data$m5), m6 = get_mode(window_data$m6), m7 = get_mode(window_data$m7), m8 = get_mode(window_data$m8) ) }) print(result, row.names = FALSE)
内容的提问来源于stack exchange,提问作者user3354212
相关产品推荐
相关产品推荐

