在R中保留数值符号变化前后指定数量的观测值
解决流量数据符号变化前后的筛选问题
核心思路
要满足你的筛选条件,关键是识别连续同符号的分段,然后找到符合「前一段≥3个同符号、后一段≥3个同符号且符号相反」的分段组合,最后提取这些分段对应的原始观测值。这里用rle()(游程编码)处理连续符号段是最高效的方式,再结合dplyr完成数据筛选与匹配。
代码实现
基于你的示例数据演示完整流程:
library(dplyr) # 示例数据 wf = data.frame(discharge = c(100, 125, 128, -25, -30, -27, 104, -23, 100, -50)) # 1. 生成符号列和连续符号段标识 wf <- wf %>% mutate( sign_d = sign(discharge), # 为每个观测分配所属的连续符号段ID run_id = with(rle(sign_d), rep(seq_along(values), lengths)) ) # 2. 统计每个符号段的关键信息 run_summary <- wf %>% group_by(run_id) %>% summarize( run_length = n(), run_sign = first(sign_d), start_row = min(row_number()), end_row = max(row_number()) ) %>% ungroup() # 3. 筛选符合条件的分段对 valid_pairs <- run_summary %>% mutate( prev_length = lag(run_length), prev_sign = lag(run_sign) ) %>% filter( run_length >= 3, prev_length >= 3, run_sign != prev_sign ) # 4. 提取目标观测值 valid_rows <- c( # 提取符合条件的前一段所有行 unlist(lapply(valid_pairs$run_id - 1, function(x) run_summary$start_row[x]:run_summary$end_row[x])), # 提取符合条件的后一段所有行 unlist(lapply(valid_pairs$run_id, function(x) run_summary$start_row[x]:run_summary$end_row[x])) ) # 最终结果 result <- wf$discharge[sort(valid_rows)] print(result) # [1] 100 125 128 -25 -30 -27
代码解释
- 符号与分段标识:用
sign()获取流量正负符号,通过rle()生成连续符号段的ID,让每个观测值对应到所属的连续符号组。 - 分段统计:对每个符号段统计长度、符号、起止行号,为后续条件判断提供基础数据。
- 筛选有效分段对:用
lag()调用前一个分段的信息,筛选出满足「前后段长度≥3、符号相反」的分段组合。 - 提取目标观测:根据有效分段的起止行号,提取对应的原始流量值,排序后得到最终结果。
适配5分钟间隔数据
针对你每小时12条的5分钟间隔数据,这段代码可直接复用——只需将wf替换为你的实际数据框,指定对应流量列即可。如果需要调整前后连续值的数量(比如对应N小时的12*N条),仅需修改filter()中run_length >= 3和prev_length >= 3的数字。
内容的提问来源于stack exchange,提问作者Jared
相关产品推荐
相关产品推荐

