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

沿Y轴裁剪时间序列数据的技术实现问询

时间序列数据的阈值裁剪实现方案

需求说明

我有一个由(datetime, float)元组组成的有序列表,所有datetime唯一且已按顺序排序,每个元组包含一个datetime对象和一个浮点数值。需要将浮点值裁剪到指定阈值以上,示例如下:

原数据

import datetime
from datetime import tzutc

a = [
    (datetime.datetime(2021, 11, 1, 0, 0, tzinfo=tzutc()), 100), 
    (datetime.datetime(2021, 11, 1, 1, 0, tzinfo=tzutc()), 9.0), 
    (datetime.datetime(2021, 11, 1, 2, 0, tzinfo=tzutc()), 100.0)
]

期望结果(阈值=10.0)

b = [
    (datetime.datetime(2021, 11, 1, 0, 0, tzinfo=tzutc()), 100), 
    (datetime.datetime(2021, 11, 1, 0, 36, tzinfo=tzutc()), 10.0),  # 线性插值计算出的交点时间
    (datetime.datetime(2021, 11, 1, 1, 24, tzinfo=tzutc()), 10.0),  # 线性插值计算出的交点时间
    (datetime.datetime(2021, 11, 1, 2, 0, tzinfo=tzutc()), 100.0)
]

原数据绘图呈V形,裁剪后需变为_/形。希望找到现成实现方案,也可接受转为等时间间隔数据的处理方式。

现成工具实现(基于Pandas)

Pandas是处理时间序列的常用工具,可以高效完成这个需求:

1. 精准计算交点的方案

通过线性插值计算阈值与曲线的交点,保留原始数据的关键节点:

import pandas as pd

df = pd.DataFrame(a, columns=['dt', 'value']).set_index('dt')
threshold = 10.0
result = []

# 加入第一个点
result.append((df.index[0], df['value'].iloc[0]))

# 遍历相邻点对处理
for i in range(1, len(df)):
    t_prev, v_prev = df.index[i-1], df['value'].iloc[i-1]
    t_curr, v_curr = df.index[i], df['value'].iloc[i]
    
    # 前点高于阈值,后点低于阈值:插入交点+后点阈值
    if v_prev > threshold and v_curr < threshold:
        delta_t = t_curr - t_prev
        delta_v = v_curr - v_prev
        t_cross = t_prev + delta_t * (threshold - v_prev) / delta_v
        result.append((t_cross, threshold))
        result.append((t_curr, threshold))
    # 前点低于阈值,后点高于阈值:插入交点+后点原值
    elif v_prev < threshold and v_curr > threshold:
        delta_t = t_curr - t_prev
        delta_v = v_curr - v_prev
        t_cross = t_prev + delta_t * (threshold - v_prev) / delta_v
        result.append((t_cross, threshold))
        result.append((t_curr, v_curr))
    # 两点都高于阈值:直接加入当前点
    elif v_prev >= threshold and v_curr >= threshold:
        result.append((t_curr, v_curr))
    # 两点都低于阈值:加入当前点的阈值替换值
    else:
        result.append((t_curr, threshold))

运行后result就是符合要求的序列,交点时间为精确计算值。

2. 等时间间隔简化方案

如果可以接受转为等时间间隔数据,处理流程更简洁:

# 生成每15分钟间隔的时间序列(可自定义频率,如'1min'/'1h')
new_index = pd.date_range(start=df.index[0], end=df.index[-1], freq='15min')
# 时间插值补全空缺数据
df_resampled = df.reindex(new_index).interpolate(method='time')
# 裁剪低于阈值的值,替换为阈值
df_clipped = df_resampled.where(df_resampled['value'] >= threshold, threshold)
# 转回元组列表格式
result = list(zip(df_clipped.index, df_clipped['value']))

这种方式无需计算精确交点,通过等间隔插值后直接替换阈值,绘图效果完全符合需求。

无依赖手动实现

如果不想依赖第三方库,纯Python也可以实现相同逻辑:

import datetime
from datetime import tzutc

threshold = 10.0
a = [
    (datetime.datetime(2021, 11, 1, 0, 0, tzinfo=tzutc()), 100), 
    (datetime.datetime(2021, 11, 1, 1, 0, tzinfo=tzutc()), 9.0), 
    (datetime.datetime(2021, 11, 1, 2, 0, tzinfo=tzutc()), 100.0)
]

result = [a[0]]

for i in range(1, len(a)):
    t_prev, v_prev = a[i-1]
    t_curr, v_curr = a[i]
    
    if v_prev > threshold and v_curr < threshold:
        # 计算时间差并插值交点
        total_seconds = (t_curr - t_prev).total_seconds()
        ratio = (threshold - v_prev) / (v_curr - v_prev)
        cross_seconds = total_seconds * ratio
        t_cross = t_prev + datetime.timedelta(seconds=cross_seconds)
        result.append((t_cross, threshold))
        result.append((t_curr, threshold))
    elif v_prev < threshold and v_curr > threshold:
        total_seconds = (t_curr - t_prev).total_seconds()
        ratio = (threshold - v_prev) / (v_curr - v_prev)
        cross_seconds = total_seconds * ratio
        t_cross = t_prev + datetime.timedelta(seconds=cross_seconds)
        result.append((t_cross, threshold))
        result.append((t_curr, v_curr))
    elif v_prev >= threshold and v_curr >= threshold:
        result.append((t_curr, v_curr))
    else:
        result.append((t_curr, threshold))

逻辑与Pandas方案一致,适合轻量场景使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:10:12