R语言中基于指定位置与因子的数据框滚动和计算问题
解决dat1新增滚动和列的需求
嘿,这个需求我熟!咱们一步步来实现,核心就是按因子匹配dat2对应数据、根据每行的from和width锁定求和区间、最后计算区间和并新增到dat1。
第一步:先模拟示例数据
先造两个测试用的数据框,方便你跟着跑:
# 模拟dat1:包含因子、起始位置、窗口宽度 dat1 <- data.frame( id = 1:4, factor = c("A", "B", "A", "B"), from = c(2, 1, 3, 2), width = c(3, 2, 2, 3) ) # 模拟dat2:按因子A/B分组的数值数据 dat2 <- data.frame( factor = rep(c("A", "B"), each = 5), value = c(10,20,30,40,50, 100,200,300,400,500) )
第二步:实现核心逻辑
这里用dplyr的逐行处理+分组拆分dat2的方式,高效又清晰:
library(dplyr) library(purrr) # 先把dat2按因子拆成分列表,后续取数更快 dat2_split <- split(dat2$value, dat2$factor) # 给dat1新增rolling_sum列 dat1 <- dat1 %>% rowwise() %>% # 开启逐行处理模式 mutate( rolling_sum = { # 1. 提取当前行因子对应的数值向量 val_vec <- dat2_split[[factor]] # 2. 计算求和区间的结束位置(from + 窗口宽度 -1 = 连续width个元素) end_pos <- from + width - 1 # 3. 边界检查:避免索引越界,超出范围返回NA(可按需调整) if (end_pos > length(val_vec) || from < 1) { NA_real_ } else { # 4. 计算区间和 sum(val_vec[from:end_pos]) } } ) %>% ungroup() # 关闭逐行模式
第三步:查看结果
运行完上面的代码,dat1会新增rolling_sum列,结果如下:
# A tibble: 4 × 5 id factor from width rolling_sum <int> <chr> <dbl> <dbl> <dbl> 1 1 A 2 3 90 2 2 B 1 2 300 3 3 A 3 2 70 4 4 B 2 3 900
补充说明
- 如果你的数据量很大,
split+rowwise的组合效率很高,比每次逐行过滤dat2要快得多。 - 边界处理部分:如果想在超出范围时自动截断到向量末尾求和,把
end_pos改成min(end_pos, length(val_vec))即可。 - 如果你更喜欢用
purrr的函数式风格,也可以用pmap实现:
dat1$rolling_sum <- pmap_dbl(dat1, function(factor, from, width, ...) { val_vec <- dat2_split[[factor]] end_pos <- from + width - 1 if (end_pos > length(val_vec) || from < 1) NA_real_ else sum(val_vec[from:end_pos]) })
内容的提问来源于stack exchange,提问作者user7715029
相关产品推荐
相关产品推荐

