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

如何计算数值超出指定范围的持续时长?

问题描述

我在处理一个看似简单的任务时卡壳了:手里有一个数值向量values和一个时间向量time,需要计算数值落在指定范围之外的总时长。

示例数据如下:

df <- data.frame(time= c(1,3:10), values= c(7,3:10))

针对这份数据,数值超出3.5到6.5范围的总时长是4.5小时。

可视化说明:
图表X轴为时间,Y轴为数值,点代表实际测量值,虚线是范围边界3.5和6.5,实线用于辅助判断穿越边界的时间点。

有没有我没注意到的简便方法来计算这个时长?

图表生成代码:

threshold_low <- 3.5
threshold_high <- 6.5

ggplot(data= df, mapping= aes(time, values)) +
  geom_point() +
  geom_line() +
  geom_hline(yintercept= c(threshold_low, threshold_high), linetype= "dashed") +
  scale_x_continuous(breaks=seq(0, 10, 1)) +
  scale_y_continuous(breaks=seq(0, 10, 1))
解决方案

核心逻辑是通过线性插值找到数值穿越阈值的时间点,再分段计算超出范围的时长并累加,这里提供两种简洁实现方式:

方法一:基础R实现

# 定义阈值
low <- 3.5
high <- 6.5

# 标记每个时间点的数值是否在范围内
df$in_range <- df$values >= low & df$values <= high

# 初始化总时长
total_out <- 0

# 遍历相邻时间点对计算时长
for(i in 2:nrow(df)) {
  t_prev <- df$time[i-1]
  t_curr <- df$time[i]
  val_prev <- df$values[i-1]
  val_curr <- df$values[i]
  in_prev <- df$in_range[i-1]
  in_curr <- df$in_range[i]
  
  # 前后都在范围外,直接累加时间差
  if(!in_prev & !in_curr) {
    total_out <- total_out + (t_curr - t_prev)
  }
  # 穿越边界,计算穿越点时间后累加对应时长
  else if(xor(in_prev, in_curr)) {
    # 处理穿越低阈值的情况
    if((val_prev < low & val_curr > low) || (val_prev > low & val_curr < low)) {
      t_cross <- t_prev + (low - val_prev) * (t_curr - t_prev) / (val_curr - val_prev)
      total_out <- total_out + ifelse(!in_prev, t_cross - t_prev, t_curr - t_cross)
    }
    # 处理穿越高阈值的情况
    if((val_prev > high & val_curr < high) || (val_prev < high & val_curr > high)) {
      t_cross <- t_prev + (high - val_prev) * (t_curr - t_prev) / (val_curr - val_prev)
      total_out <- total_out + ifelse(!in_prev, t_cross - t_prev, t_curr - t_cross)
    }
  }
}

# 输出结果
total_out
# [1] 4.5

方法二:tidyverse工具链简化

如果习惯用dplyr和purrr,可以更简洁地实现:

library(dplyr)

low <- 3.5
high <- 6.5

df %>%
  mutate(
    in_range = between(values, low, high),
    time_diff = time - lag(time),
    prev_val = lag(values),
    prev_in = lag(in_range)
  ) %>%
  slice(-1) %>%
  mutate(
    out_duration = case_when(
      !prev_in & !in_range ~ time_diff,
      !prev_in & in_range ~ {
        t_cross <- lag(time) + ifelse(prev_val > high, 
                                     (high - prev_val) * time_diff / (values - prev_val),
                                     (low - prev_val) * time_diff / (values - prev_val))
        t_cross - lag(time)
      },
      prev_in & !in_range ~ {
        t_cross <- lag(time) + ifelse(values > high,
                                     (high - prev_val) * time_diff / (values - prev_val),
                                     (low - prev_val) * time_diff / (values - prev_val))
        time - t_cross
      },
      TRUE ~ 0
    )
  ) %>%
  pull(out_duration) %>%
  sum()
# [1] 4.5

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 05:36:35