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

如何缩放整数列表以适配800点波形图展示?

波形数据降采样(保留形态与极值)的实用方案

你遇到的问题本质是固定点数的时间序列降采样——既要把从几十到百万级的波形数据压缩到800个点,又不能丢失整体趋势和关键极值。步长取点容易跳过峰值,邻域平均会抹平波形细节,以下是几个针对性的解决方案:

1. LTTB降采样算法(首选)

这个算法专门为波形/时间序列数据设计,能在固定输出点数的前提下,最大程度保留数据的形态、峰值和谷值。核心逻辑是将数据划分为800个桶,每个桶内选择一个点,使得相邻三个桶的点构成的三角形面积最大——这样能自动优先保留那些对波形形态影响最大的极值点。

操作步骤:

  • 如果原数据长度 ≤800:直接输出所有数据点,无需降采样。
  • 如果原数据长度 >800:
    1. 将数据均匀划分为800个桶,最后一个桶可容纳剩余的少量数据。
    2. 第一个桶取第一个点,最后一个桶取最后一个点。
    3. 对中间的每个桶,计算该桶内每个点与前一个已选点、后一个桶中点组成的三角形面积,选择面积最大的点作为该桶的代表点。

伪代码示例:

def lttb_downsample(data, n_out=800):
    data_len = len(data)
    if data_len <= n_out:
        return data
    # 划分桶
    bucket_size = data_len / n_out
    buckets = []
    for i in range(n_out):
        start = int(i * bucket_size)
        end = int((i+1)*bucket_size) if i != n_out-1 else data_len
        buckets.append(data[start:end])
    # 初始化结果(首尾点固定)
    result = [buckets[0][0], buckets[-1][-1]]
    # 处理中间桶
    for i in range(1, n_out-1):
        prev_point = result[-1]
        next_bucket = buckets[i+1]
        # 简化取后一个桶的中点
        next_mid = (next_bucket[0] + next_bucket[-1]) / 2
        max_area = -1
        best_point = None
        for point in buckets[i]:
            # 计算三角形面积(省略1/2系数不影响比较)
            area = abs((prev_point - point) * (next_mid - prev_point) - (prev_point - prev_point) * (point - prev_point))
            if area > max_area:
                max_area = area
                best_point = point
        result.insert(-1, best_point)
    return result

优势:

  • 完美保留峰值、谷值和整体趋势,不会像均值法那样抹平波形细节。
  • 计算效率较高,处理180万级数据也能快速完成。

2. 分块极值优先采样

如果不想实现复杂的LTTB,这个简化方案也能满足需求:核心是每个采样块优先保留极值,再用中位数补充(中位数比均值更能抵抗异常值,保留形态)。

操作步骤:

  1. 计算块大小:block_size = (len(data) + 800 - 1) // 800(向上取整),若原数据长度<800则block_size=1。
  2. 遍历每个块:
    • 若块内数据量 ≤3:直接取所有点(总点数不会超过800)。
    • 若块内数据量 >3:检查块内是否存在接近边界的极值(比如值≥190或≤10,对应你的0-200取值范围),如果有则取该极值点;如果没有则取块内的中位数。

伪代码示例:

def extreme_priority_downsample(data, n_out=800):
    data_len = len(data)
    if data_len <= n_out:
        return data
    block_size = (data_len + n_out - 1) // n_out
    result = []
    for i in range(n_out):
        start = i * block_size
        end = min((i+1)*block_size, data_len)
        block = data[start:end]
        # 筛选接近极值的点
        extremes = []
        for x in block:
            if x >= 190 or x <= 10:
                extremes.append(x)
        if extremes:
            # 取最接近边界的极值
            result.append(max(extremes) if max(extremes) >= 190 else min(extremes))
        else:
            # 取中位数
            sorted_block = sorted(block)
            mid_idx = len(sorted_block) // 2
            result.append(sorted_block[mid_idx])
    return result

优势:

  • 实现简单,针对你的0-200取值范围做了针对性优化,确保峰值不丢失。
  • 计算速度极快,适合超大规模数据。

3. 短数据补全(可选)

如果原数据长度远小于800(比如只有50个点),可以用线性插值补全到800个点,让波形在画布上更饱满,同时避免过度插值失真:

import numpy as np
def interpolate_short_data(data, n_out=800):
    if len(data) >= n_out:
        return data
    x_old = np.linspace(0, 1, len(data))
    x_new = np.linspace(0, 1, n_out)
    return np.interp(x_new, x_old, data).tolist()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:21:13