如何用R函数式编程实现带中断的amps序列求和及索引返回
解决方案:用分组汇总实现函数式处理
这个需求非常适合用分组+汇总的函数式思路来解决,完全不需要循环。核心是把连续的非0值和单独的0值分成不同的组,然后对每个组做针对性处理。
方法1:使用dplyr + data.table的rleid(兼容性广)
rleid函数可以把连续的相同逻辑值(这里是amps == 0)归为同一个组,正好帮我们把连续非0值、单个0值分开:
library(dplyr) library(data.table) df <- tibble::tibble(index = seq(1:8), amps = c(7, 6, 7, 0, 7, 6, 0, 6)) result <- df %>% # 生成分组ID:连续非0为一组,每个0单独一组 mutate(group = rleid(amps == 0)) %>% group_by(group) %>% summarise( # 非0组取第一个index,0组取自身index index = first(index), # 非0组求和,0组直接取0 amps = if (any(amps == 0)) first(amps) else sum(amps) ) %>% ungroup() %>% select(-group) print(result)
方法2:仅用dplyr(需要dplyr 1.1.0+)
如果你不想依赖data.table,可以用dplyr自带的consecutive_id函数,功能和rleid一致:
library(dplyr) df <- tibble::tibble(index = seq(1:8), amps = c(7, 6, 7, 0, 7, 6, 0, 6)) result <- df %>% mutate(group = consecutive_id(amps == 0)) %>% group_by(group) %>% summarise( index = first(index), amps = if (any(amps == 0)) first(amps) else sum(amps) ) %>% ungroup() %>% select(-group) print(result)
运行结果
两种方法都会得到你预期的输出:
# A tibble: 5 × 2 index amps <int> <dbl> 1 1 20 2 4 0 3 5 13 4 7 0 5 8 6
逻辑解释
- 分组逻辑:
rleid(amps == 0)会给连续的非0值分配同一个组ID,每个0值单独分配一个新组ID,这样我们就把数据拆成了5个处理单元:[1-3行]、[4行]、[5-6行]、[7行]、[8行]。 - 组内处理:对每个组,判断是否包含0:
- 包含0的组:直接保留该组的index和0值;
- 不包含0的组:计算该组amps的总和,同时保留组内第一个index。
这种方法完全遵循函数式编程的思路,代码简洁易读,也方便后续扩展。
内容的提问来源于stack exchange,提问作者Blake Shurtz
相关产品推荐
相关产品推荐

