如何在R中按滑动窗口规则构建计数填充矩阵?
用R实现滑动窗口分类计数矩阵
当然可以搞定这个需求!我来一步步带你实现,先从模拟你的数据场景开始,再分两种方式(用便捷的包和纯Base R)来写代码,你可以按需选择。
第一步:模拟示例数据
先模拟你提到的图1格式的数据,方便后续测试:
set.seed(123) # 固定随机种子,确保结果可复现 df <- data.frame( 分类列 = c("a", "b", "c", "b", "a", "c", "b"), 响应变量 = c("Yes", "Yes", "Yes", "Yes", "No", "Yes", "Yes") ) print(df)
第二步:核心逻辑说明
我们要实现的是:
- 滑动窗口大小为3,每次滑动1步(取连续3行)
- 仅当窗口内所有响应变量为Yes时(如果你的条件是其他,比如窗口最后一行是Yes,可以后面调整),统计窗口内各分类的出现次数
- 将每个符合条件的窗口统计结果,作为结果矩阵的一行,所有分类作为列,未出现的分类填0
方式一:用slider包快速实现(推荐)
slider包专门处理滑动窗口操作,代码更简洁:
# 先安装并加载包(首次使用需要安装) # install.packages("slider") library(slider) library(tidyr) # 用于转换宽长格式 # 定义窗口处理函数 process_window <- function(window_df) { # 这里的条件是窗口内所有响应变量为Yes,可根据你的需求修改 if(all(window_df$响应变量 == "Yes")) { # 统计分类出现次数 count_table <- table(window_df$分类列) # 转换为宽格式,缺失分类自动填0 tidyr::pivot_wider( as.data.frame(count_table, stringsAsFactors = FALSE), names_from = Var1, values_from = Freq, values_fill = 0 ) } else { # 不满足条件就返回NULL,自动跳过 NULL } } # 生成滑动窗口并处理 window_size <- 3 result_list <- slide_df(df, .f = process_window, .before = window_size - 1, .complete = TRUE) # 转换为最终矩阵 result_matrix <- as.matrix(do.call(rbind, result_list)) print(result_matrix)
方式二:纯Base R实现(无需额外包)
如果不想安装新包,用Base R也能实现:
window_size <- 3 n_rows <- nrow(df) start_indices <- 1:(n_rows - window_size + 1) result_list <- list() # 遍历每个窗口 for(i in start_indices) { # 提取当前窗口数据 current_window <- df[i:(i + window_size - 1), ] # 判断是否满足条件(这里是窗口内所有Yes) if(all(current_window$响应变量 == "Yes")) { # 统计分类次数 category_counts <- table(current_window$分类列) # 获取所有唯一分类,确保列完整 all_categories <- unique(df$分类列) # 初始化当前行,所有分类默认0 current_result <- rep(0, length(all_categories)) names(current_result) <- all_categories # 填充计数 current_result[names(category_counts)] <- category_counts # 添加到结果列表 result_list[[length(result_list) + 1]] <- current_result } } # 合并为矩阵 result_matrix <- do.call(rbind, result_list) print(result_matrix)
调整条件提示
如果你的条件不是“窗口内所有Yes”,而是比如窗口的最后一行响应变量为Yes,只需要修改判断条件:
- 在
process_window函数里把all(window_df$响应变量 == "Yes")改成tail(window_df$响应变量, 1) == "Yes" - 在Base R的循环里改成
if(tail(current_window$响应变量, 1) == "Yes")
内容的提问来源于stack exchange,提问作者user080391
相关产品推荐
相关产品推荐

