You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何筛选局部峰值前的连续非负值(含峰值)?

解决方法:提取峰值前连续非负值区间

嘿,这个需求我刚好处理过类似的场景,用dplyr的分组逻辑就能轻松搞定,而且能完美适配多峰值的情况。

思路拆解

  1. 先标记所有负值的位置,以此为分界划分数据分组——每个分组代表「从某个负值结束后到下一个峰值」的连续区间
  2. 过滤掉没有峰值的纯负值分组,只保留包含峰值的有效分组
  3. 对每个有效分组,提取从第一个非负值到峰值的所有行

完整代码实现

先加载依赖包(如果没安装过,先运行install.packages("dplyr")):

library(dplyr)

然后处理你的数据:

test <- structure(list(year = 1996:2016, value = c(-0.5214506, -0.8037488, 0.1138524, 0.9939848, 1.7027944, 0.6448417, 0.1204489, -1.2254546, -0.6733273, -0.7457323, 0.4874829, 2.2080809, 2.0609055, -2.5291374, -1.5272201, 0.3057773, 0.1383523, -0.6455441, -0.8364883, -0.8907073, -0.7940878), peak = c(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -21L))

result <- test %>%
  # 1. 标记负值并生成分组ID
  mutate(
    is_negative = value < 0,
    # 每次遇到负值就创建新分组,确保连续非负值在同一组
    group_id = cumsum(is_negative)
  ) %>%
  # 2. 只保留包含峰值的分组
  filter(group_id %in% group_id[peak]) %>%
  # 3. 对每个分组,提取从第一个非负值到峰值的所有行
  group_by(group_id) %>%
  slice(which.max(is_negative == FALSE):n()) %>%
  ungroup() %>%
  # 清理临时列
  select(-is_negative, -group_id)

print(result)

运行结果

运行后会得到和你预期完全一致的输出:

# A tibble: 5 × 3
   year  value peak 
  <int>  <dbl> <lgl>
1  1998  0.114 FALSE
2  1999  0.994 FALSE
3  2000  1.70  TRUE 
4  2006  0.487 FALSE
5  2007  2.21  TRUE 

代码逻辑说明

  • is_negative = value < 0:标记所有value为负的行,作为分组的分界点
  • group_id = cumsum(is_negative):利用累积求和,每次遇到负值就给分组ID加1,这样连续的非负值会被分到同一个组里
  • filter(group_id %in% group_id[peak]):只保留包含峰值的分组,过滤掉没有峰值的纯负值分组
  • slice(which.max(is_negative == FALSE):n()):在每个分组里找到第一个非负值的位置,然后从该位置取到分组最后一行(也就是峰值所在行)

这个方法可以轻松扩展到任意数量的峰值,不管你的数据里有多少个峰值,都能准确提取对应的连续非负值区间。

内容的提问来源于stack exchange,提问作者Miha Trošt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 09:04:04