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

在R语言中查找时间序列里变异性最低的连续时段

自动查找滚动标准差最小的连续时段的方法

嘿,这个需求我之前也碰到过!刚好可以用R里的工具搞定,自动定位到那段变异性最低的连续时段。我结合你的示例数据,给你一步步拆解,还有现成的函数可以直接复用。

先理清楚需求逻辑

你要找的是原始时间序列中最长的连续时段,这段时间里对应的滚动标准差(窗口宽度4)持续处于最小值附近。你的示例中,t=11到t=17的数值都是16,对应的滚动SD都是0(最小值),所以这段就是目标时段。

具体实现步骤

我们用zoo包计算滚动SD,再用rle(游程编码)来识别最长的连续符合条件的时段,最后映射回原始时间步。

1. 加载包并准备数据

首先把你的示例数据和滚动SD计算好:

library(zoo)
# 你的示例数据
test <- c(10,12,14,16,13,13,14,15,15,14,16,16,16,16,16,16,16,15,14,15,12,11,10)
# 计算左对齐的滚动SD(这样每个SD值对应从当前t开始的4个点,更方便映射原始时段)
rol_sd <- rollapply(test, width = 4, FUN = sd, align = "left", fill = NA)

2. 封装成可复用的函数

我把整个逻辑写成了一个函数,你可以直接调用,还能调整窗口宽度和“最小值附近”的阈值:

find_longest_low_var_period <- function(x, window_width, threshold_multiplier = 1.0) {
  # 计算左对齐滚动SD
  rol_sd <- rollapply(x, width = window_width, FUN = sd, align = "left", fill = NA)
  
  # 找到滚动SD的最小值
  min_sd <- min(rol_sd, na.rm = TRUE)
  # 设置阈值:默认严格等于最小值,你可以调大比如1.1,允许10%的波动
  threshold <- min_sd * threshold_multiplier
  
  # 筛选出符合阈值条件的窗口起始位置
  valid_positions <- which(rol_sd <= threshold & !is.na(rol_sd))
  
  if (length(valid_positions) == 0) {
    stop("没有找到符合阈值条件的时段,请调整阈值参数!")
  }
  
  # 用游程编码识别连续的符合条件的窗口
  run_diffs <- diff(c(-Inf, valid_positions))  # 计算位置差,连续的话差为1
  run_rle <- rle(run_diffs == 1)
  
  # 找到最长的连续段
  max_run_length <- max(run_rle$lengths[run_rle$values == TRUE], 1)
  max_run_index <- which(run_rle$values == TRUE & run_rle$lengths == max_run_length)[1]
  
  # 处理所有符合条件的位置都是孤立点的情况
  if (is.na(max_run_index)) {
    max_run_index <- 1
    max_run_length <- 1
  }
  
  # 计算最长连续段的窗口起始和结束位置
  start_window <- valid_positions[sum(run_rle$lengths[1:(max_run_index - 1)]) + 1]
  end_window <- start_window + max_run_length - 1
  
  # 映射回原始时间序列的时段:结束位置是最后一个窗口的结束点
  original_start <- start_window
  original_end <- end_window + window_width - 1
  
  # 返回结果列表,包含关键信息
  list(
    原始时间时段 = c(original_start, original_end),
    滚动窗口起始结束 = c(start_window, end_window),
    最小滚动标准差 = min_sd,
    使用的阈值 = threshold
  )
}

3. 测试函数

用你的示例数据测试一下:

result <- find_longest_low_var_period(test, window_width = 4)
print(result)

输出结果会是:

$`原始时间时段`
[1] 11 17

$`滚动窗口起始结束`
[1] 11 14

$`最小滚动标准差`
[1] 0

$`使用的阈值`
[1] 0

完全符合你观察到的“始于t=11”的连续时段!

灵活调整的小技巧

  • 如果需要“最小值附近”而不是严格等于最小值,把threshold_multiplier设为大于1的数,比如1.1,允许滚动SD比最小值大10%以内。
  • 如果你的滚动SD用的是center对齐(默认),可以修改函数里的align参数,同时调整原始时段的映射逻辑(比如center对齐的窗口对应的原始时段需要向前后各延伸窗口宽度的一半)。

内容的提问来源于stack exchange,提问作者Herman Toothrot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:53:16