V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
sober1215zxy
V2EX  ›  Python

请教关于阶梯曲线数据的处理问题

  •  
  •   sober1215zxy · 2022-04-10 23:12:10 +08:00 · 1663 次点击
    这是一个创建于 960 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:

    1. csv 数据用 matplotlib 绘制“能量-时间”曲线。 2.整个过程中,能量会在一定时间范围内保持基本稳定,然后上升或下降到一个新的范围内继续保持一段时间,直到结束,整个曲线因此会出现多个阶梯。 需求: 1.想要统计一共有多少个台阶 2.每个台阶的能量均值、该均值下的开始时间、结束时间和持续时间。 个人思路: 1.从 CSV 数据角度出发利用数据分析设定触发条件进行统计 2.先绘制出图像然后对图像进行分析 个人感觉思路 2 反而复杂化了,不知道大家有没有好的想法,或者看过类似的处理案例(感觉阶梯曲线分析应该是有的),谢谢大家了。
    4 条回复    2022-04-11 16:21:18 +08:00
    necomancer
        1
    necomancer  
       2022-04-11 16:08:42 +08:00   ❤️ 1
    看一下 meanshift 算法, scikit
    necomancer
        2
    necomancer  
       2022-04-11 16:16:02 +08:00
    from sys import argv

    import numpy as np
    from matplotlib import pyplot as plt
    from scipy.ndimage import gaussian_filter1d
    from scipy.stats import linregress
    from sklearn.cluster import MeanShift

    x, y = np.loadtxt(argv[1]).T
    y_orig = np.copy(y)
    y = np.pad(y, (y.shape[0] // 10, 0), mode='edge') # 往前插 10 分之一的 y[0],相当于 y[0]是独立的一个 cluster
    y = gaussian_filter1d(y, 85, mode='nearest') # 宽度自己调到合适,没啥涨落的数据可以不用

    clustering = MeanShift(bandwidth=None).fit(y[:, None])
    lbs = clustering.labels_[y_orig.shape[0] // 10:] # 前面的可以不要了,第一个值相当于 y[0]的 label

    plt.plot(x, y_orig, alpha=.5)
    start, xmins = [], [], []
    for c in set(lbs):
    ....r = linregress(x[lbs == c], y_orig[lbs == c])
    ....plt.plot(x[lbs == c], r.slope * x[lbs == c] + r.intercept) # 当数据波动大的时候,用了线性拟合画出来效果好一些,如果你数据的 unitstep 很平,用下面直接画平台值就行
    ....# plt.hlines(np.mean(y_orig[lbs == c]), xmin=x[lbs==c][0], xmax=x[lbs==c][-1], color='k', lw=4)
    ....start.append(r.slope * x[lbs == c][0] + r.intercept)
    ....xmins.append(x[lbs == c][0])
    print([x for _, x in sorted(zip(xmins, start))]) # sort from left to right
    plt.show()
    necomancer
        3
    necomancer  
       2022-04-11 16:17:06 +08:00
    start, xmins = [], []
    写错了。。。
    necomancer
        4
    necomancer  
       2022-04-11 16:21:18 +08:00
    如果你数据抖动非常小的话,高斯平滑一下求拉普拉斯,零点就是 step 边界,或者跳跃如果非常 sharp ,也可以试试 canny filter ,效果好,参数少并且简单。meanshift 方法更适用于数据抖动比较大,step 其实不能太算 step ,反而带着斜率
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2714 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 15:24 · PVG 23:24 · LAX 07:24 · JFK 10:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.