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

2022-04-10 23:12:10 +08:00
 sober1215zxy

背景:

  1. csv 数据用 matplotlib 绘制“能量-时间”曲线。 2.整个过程中,能量会在一定时间范围内保持基本稳定,然后上升或下降到一个新的范围内继续保持一段时间,直到结束,整个曲线因此会出现多个阶梯。 需求: 1.想要统计一共有多少个台阶 2.每个台阶的能量均值、该均值下的开始时间、结束时间和持续时间。 个人思路: 1.从 CSV 数据角度出发利用数据分析设定触发条件进行统计 2.先绘制出图像然后对图像进行分析 个人感觉思路 2 反而复杂化了,不知道大家有没有好的想法,或者看过类似的处理案例(感觉阶梯曲线分析应该是有的),谢谢大家了。
1654 次点击
所在节点    Python
4 条回复
necomancer
2022-04-11 16:08:42 +08:00
看一下 meanshift 算法, scikit
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
2022-04-11 16:17:06 +08:00
start, xmins = [], []
写错了。。。
necomancer
2022-04-11 16:21:18 +08:00
如果你数据抖动非常小的话,高斯平滑一下求拉普拉斯,零点就是 step 边界,或者跳跃如果非常 sharp ,也可以试试 canny filter ,效果好,参数少并且简单。meanshift 方法更适用于数据抖动比较大,step 其实不能太算 step ,反而带着斜率

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846150

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX