Python scipy单变量样条线在打印时始终返回线性ish样条线
我有以下一组数据(Python scipy单变量样条线在打印时始终返回线性ish样条线,python,matplotlib,scipy,spline,timeserieschart,Python,Matplotlib,Scipy,Spline,Timeserieschart,我有以下一组数据(pandas.DataFrame),我想使用scipy.interpolate.UnivariateSpline来拟合。让我们调用datadata Date 2018-04-02 09:00:00 16249 2018-04-02 10:00:00 45473 2018-04-02 11:00:00 32050 2018-04-02 12:00:00 35898 2018-04-02 13:00:00 21577 2018-04-02 1
pandas.DataFrame
),我想使用scipy.interpolate.UnivariateSpline
来拟合。让我们调用datadata
Date
2018-04-02 09:00:00 16249
2018-04-02 10:00:00 45473
2018-04-02 11:00:00 32050
2018-04-02 12:00:00 35898
2018-04-02 13:00:00 21577
2018-04-02 14:00:00 30545
2018-04-02 15:00:00 60925
2018-04-02 16:00:00 47124
2018-04-03 09:00:00 18534
2018-04-03 10:00:00 36064
2018-04-03 11:00:00 32387
2018-04-03 12:00:00 15903
2018-04-03 13:00:00 22291
2018-04-03 14:00:00 26367
2018-04-03 15:00:00 66269
2018-04-03 16:00:00 38478
2018-04-04 09:00:00 15803
2018-04-04 10:00:00 22511
2018-04-04 11:00:00 33123
2018-04-04 12:00:00 21000
2018-04-04 13:00:00 23132
2018-04-04 14:00:00 39270
2018-04-04 15:00:00 102544
2018-04-04 16:00:00 143421
2018-04-04 17:00:00 200
2018-04-05 09:00:00 23377
2018-04-05 10:00:00 52089
2018-04-05 11:00:00 99298
2018-04-05 12:00:00 24627
2018-04-05 13:00:00 33467
2018-04-05 14:00:00 26498
2018-04-05 15:00:00 114794
2018-04-05 16:00:00 44904
2018-04-06 09:00:00 12180
2018-04-06 10:00:00 41658
2018-04-06 11:00:00 64066
2018-04-06 12:00:00 12517
2018-04-06 13:00:00 12610
2018-04-06 14:00:00 43544
2018-04-06 15:00:00 65533
2018-04-06 16:00:00 123885
2018-04-09 09:00:00 13425
2018-04-09 10:00:00 38354
2018-04-09 11:00:00 59491
2018-04-09 12:00:00 21402
2018-04-09 13:00:00 24550
2018-04-09 14:00:00 25189
2018-04-09 15:00:00 67751
2018-04-09 16:00:00 16071
2018-04-10 09:00:00 35587
2018-04-10 10:00:00 58667
2018-04-10 11:00:00 41831
2018-04-10 12:00:00 35196
2018-04-10 13:00:00 22611
2018-04-10 14:00:00 23070
2018-04-10 15:00:00 40819
2018-04-10 16:00:00 20337
2018-04-11 09:00:00 7962
2018-04-11 10:00:00 23982
2018-04-11 11:00:00 21794
2018-04-11 12:00:00 16835
2018-04-11 13:00:00 16821
2018-04-11 14:00:00 13270
2018-04-11 15:00:00 34954
2018-04-11 16:00:00 15772
2018-04-12 09:00:00 8587
2018-04-12 10:00:00 47950
2018-04-12 11:00:00 24742
2018-04-12 12:00:00 16743
2018-04-12 13:00:00 21917
2018-04-12 14:00:00 43272
2018-04-12 15:00:00 50630
2018-04-12 16:00:00 104656
2018-04-13 09:00:00 15282
2018-04-13 10:00:00 30304
2018-04-13 11:00:00 65737
2018-04-13 12:00:00 17467
2018-04-13 13:00:00 10439
2018-04-13 14:00:00 19836
2018-04-13 15:00:00 52051
2018-04-13 16:00:00 99462
到目前为止,我所做的是:
import matplotlib.pyplot as plt
import numpy as np
import scipy.interpolate as interp
x = [i for i in range(1, data.size+1)] # this gives x as an array from 1 to 82.
spl = interp.UnivariateSpline(x, data.values, s=0.5)
xx = np.linspace(min(x), max(x), 1000) # 1000 is an arbitrary number here.
plt.plot(x, data.values, 'bo')
plt.plot(xx, spl(xx), 'r')
plt.show()
# the plot is below and it seems to be very linear and does not look like a cubic spline at all. Cubic Spline is the default.
当我针对x
运行spl
时,其他变量保持不变,即:
plt.plot(x, spl(x), 'r')
我得到以下信息:
唯一不同的是y轴的顶部为14000,这似乎意味着之前的图显示了一定程度的曲率。(还是没有?)
我不确定我错过了什么,但我显然错过了什么。我对python中的spline
fitting仍然是个新手
你能告诉我如何正确拟合上面的时间序列吗
编辑
根据你的评论,我想添加另一个情节,希望能更好地解释我自己。我并不是说它是线性的,但我找不到更好的词了。举例来说
xxx = [10,20,40,60,80]
plt(x, data.values, 'bo')
plt(xx, sp(xx), 'r')
plt.show()
我认为下面的情节在我看来是相当线性的。我猜,也许我的问题应该是,scipy.UnivariateSpline
到底是如何工作的
它是否仅显示在我们提供的点处评估的值的曲线图(例如,对于该曲线图,它是xxx
)
我期待一个更平滑的曲线图。问题的答案显示了我所期待的情节;它看起来更像是分段三次函数生成的曲线图,而我的曲线图在我看来是线性的(或一阶的,如果更合适的话)。您拥有的数据集看起来更像平滑曲线可以遵循的东西。你和SciPy之间没有问题;您对数据有问题 通过增加参数
s
,可以获得与数据越来越偏离的逐渐平滑的曲线图,最终接近三次多项式,这是数据的“最佳”最小二乘拟合。但这里“最好”的意思是“非常糟糕,可能一文不值”。平滑曲线可用于显示数据已遵循的模式。如果数据不符合平滑模式,则不应为了绘制而绘制曲线。第一个图上的数据点应按原样显示,无任何连接或近似曲线
数据来自9:00到16:00的每小时读数(其中一个17:00的零散值混合在一起-扔掉)。这种结构很重要。不要假装周二9:00是周一16:00后一小时发生的事情
数据可以通过每日总计进行有意义的汇总
Day Total
2018-04-02 289841
2018-04-03 256293
2018-04-04 401004
2018-04-05 419054
2018-04-06 375993
2018-04-09 266233
2018-04-10 278118
2018-04-11 151390
2018-04-12 318497
2018-04-13 310578
以及每小时平均数(9:00时的平均事件数,全天等)
在这些事情上,我们可以观察到一些模式。这是每小时一次的:
hourly_averages = np.array([16698.6, 39705.2, 47451.9, 21758.8, 20941.5, 29086.1, 65627, 65411])
hours = np.arange(9, 17)
hourly_s = 0.1*np.diff(hourly_averages).max()**2
hourly_spline = interp.UnivariateSpline(hours, hourly_averages, s=hourly_s)
xx = np.linspace(min(hours), max(hours), 1000) # 1000 is an arbitrary number here.
plt.plot(hours, hourly_averages, 'bo')
plt.plot(xx, hourly_spline(xx), 'r')
plt.show()
曲线显示午餐休息时间和下班高峰时间。我对s
的选择是0.1*np.diff(小时平均值)。max()**2
不是规范的,但它认识到s
的比例是残差的平方。(). 对于每日平均值,我将使用相同的选择:
daily_totals = np.array([289841, 256293, 401004, 419054, 375993, 266233, 278118, 151390, 318497, 310578])
days = np.arange(len(daily_totals))
daily_s = 0.1*np.diff(daily_totals).max()**2
daily_spline = interp.UnivariateSpline(days, daily_totals, s=daily_s)
xx = np.linspace(min(days), max(days), 1000) # 1000 is an arbitrary number here.
plt.plot(days, daily_totals, 'bo')
plt.plot(xx, daily_spline(xx), 'r')
plt.show()
这不太有用。也许我们需要更长时间的观察。也许我们不应该假装星期一在星期五之后。也许应该对一周中的每一天进行平均,以揭示一周的模式,但只有两周的时间是不够的
技术细节:方法
单变量样条线
选择尽可能少的节数,以便与数据的某个加权偏差平方和最多为s
。对于大的s
这意味着只有很少的节点,直到没有节点,我们得到一个三次多项式。需要多大的s
取决于垂直方向上的振荡量,在本例中,振荡量非常高。为什么说曲线图看起来是线性的?在第一个图中,放大间隔[20]样条曲线拟合看起来正确,执行得也正确。我不太理解它的问题。所以当你说“我显然错过了一些东西”,你是什么意思?绘图有什么问题,你希望它看起来如何?@WarrenWeckesser为不准确感到抱歉。我并不是真的想说“线性”。我添加了另一个绘图来帮助解释我的问题。@importantanceofbeingerre谢谢你的时间。我可能在UnivariateSpline
。我添加了一个指向更像我想要的绘图的链接。我通常使用作为样条曲线。当我使用r
在r中进行样条曲线时,它看起来是正确的,也是我所期望的。谢谢你的回答。我实际上已经尝试过将gam
增加到一些荒谬的数字。例如s
,s=100
。我想我必须放大才能看到实际的平滑效果。我添加的最后一个图呢?它看起来像是s=500
只在提供的那些点上计算值,并简单地画了一条直线来连接它们。嗯……当我阅读时,只有14个点被传递到单变量样条线
,图看起来不太复杂糟糕的是?唯一的区别是我使用的是单变量样条线
,答案是pyplot.plot
。只是为了确保每个人都在同一页上:如果你有7个点并绘制正弦曲线,pylab.plot
it,仅仅是因为您仅使用7个点对正弦进行采样。如果您使用1000个点对正弦进行采样,x=np.array([0,1,2,3,4,5,6]);y=np sin x;plot(x,y)
,您当然会得到。@ImportanceOfBeingErnest所以它看起来确实是我应该更多使用的绘图。我将很快再尝试几次。非常感谢!x=np.linspace(0,61000)
daily_totals = np.array([289841, 256293, 401004, 419054, 375993, 266233, 278118, 151390, 318497, 310578]) days = np.arange(len(daily_totals)) daily_s = 0.1*np.diff(daily_totals).max()**2 daily_spline = interp.UnivariateSpline(days, daily_totals, s=daily_s) xx = np.linspace(min(days), max(days), 1000) # 1000 is an arbitrary number here. plt.plot(days, daily_totals, 'bo') plt.plot(xx, daily_spline(xx), 'r') plt.show()