Certain arrangements of smoothing intensity, weights and xdata, in particular irregularly spaced data where some xvalues are rather close together, causes CubicSmoothingSpline to produce a first derivative that is not the integral of the second derivative. This can be exacerbated by certain weights. In particular, the first derivative can be very non-smooth, even though the second derivative is smooth.
This is important, because a very common use-case for CubicSmoothingSpline (as opposed to say LOWESS smoothing) is to ensure smooth derivatives.
Code demonstrating the problem (apologies for the large amount of data in the test case - it's some real data from a project I am working on, and I haven't been able to determine exactly which features are causing the problem, though enforcing a minimum x spacing seems to work as shown, and removing weights reduces the issue but doesn't eliminate it).
As you can see, the resulting splines all give quite different estimates of the data, so what we mean by "correct" is up for discussion.
# Problem case giving unsmooth derivatives
# The first derivative of the smoothed function is NOT the integral of the second derivative
# (notice small discontinuities / steps)
# This is particularly acute when certain weight values play a part as well
x = [-288.55699074,-288.28206019,-287.66591435,-287.64053241,-286.65069444,
-286.65068866,-285.52694444,-285.23972222,-284.64372685,-284.44784722,
-283.38444444,-283.38365741,-282.55511574,-282.53914352,-281.63871528,
-280.46857639,-280.46855324,-278.46340278,-278.37118056,-277.58601852,
-277.58574074,-276.54689815,-276.54663194,-275.62396991,-274.54616898,
-274.54615741,-273.55909722,-273.38333333,-272.57217593,-272.5721412,
-269.7065625,-269.51540509,-268.61980324,-268.60930556,-267.57458333,
-267.57457755,-263.58122685,-259.53576389,-258.82375,-258.82333333,
-257.85988426,-257.85986111,-254.25375,-254.25374421,-253.60337963,
-253.60333333,-251.7546875,-251.75461806,-250.94400463,-247.44850694,
-244.78422454,-244.7834838,-243.80513889,-243.80423611,-242.545625,
-242.54511574,-241.58532407,-241.58527778,-240.53894676,-240.53893519,
-239.59284722,-239.59278935,-234.86810185,-234.86706019,-229.50280093,
-229.50270833,-228.67150463,-228.67148148,-227.83733796,-227.63991898,
-225.75958333,-225.75953704,-224.77252315,-224.77251157,-223.98796296,
-223.98793981,-222.53775463,-222.53773148,-221.47532407,-219.68340278,
-219.6830787,-218.77277778,-218.77275463,-216.28890046,-216.28887731,
-215.52909722,-214.40041667,-214.40039352,-212.61553241,-212.61550926,
-211.81768519,-211.47722222,-211.47716435,-208.37016204,-208.36606481,
-207.62565972,-206.73474537,-206.73467593,-205.8547338,-205.83864583,
-204.94078704,-204.85533565,-203.72707176,-203.72493056,-203.72258102,
-203.57979167,-203.57978009,-202.72645833,-202.68732639,-202.54818287,
-201.68228009,-201.51018519,-201.43820602,-200.49405093,-200.49201389,
-199.62027778,-199.50150463,-199.50037037,-199.49247685,-198.74945602,
-198.74351852,-197.64726852,-197.6459375,-197.48726852,-196.49546296,
-196.43032407,-195.52611111,-195.46309028,-194.50974537,-194.50868056,
-193.46177083,-193.46171296,-192.88958333,-192.88957176,-191.64532407,
-191.64497685,-190.5394213,-190.51228009,-189.69407407,-189.69158565,
-188.55555556,-188.43287037,-186.77581019,-186.76670139,-184.90331019,
-184.90259259,-182.46954861,-182.46900463,-181.82518519,-180.79622685,
-180.79261574,-179.48037037,-179.47877315,-178.50547454,-178.50518519,
-177.54893519,-177.5484838,-176.70898148,-176.70897569,-172.47497685,
-171.58761574,-171.58756944,-169.23037037,-169.19318287,-168.54819444,
-165.79189815,-165.79189236,-165.79136574,-164.7587037,-164.75511574,
-161.85717593,-161.85717014,-160.74731481,-160.74730903,-156.4134838,
-156.41269676,-155.81989583,-155.81988426,-154.45269676,-154.43328704,
-153.80079861,-153.80032407,-152.54888889,-152.54819444,-148.93758102,
-147.84275463,-147.84274884,-146.98821759,-145.84561343,-145.84560185,
-140.25047454,-140.25046296,-138.99819444,-138.99818866,-137.92916667,
-137.85449074,-136.48898148,-136.48894676,-124.4325,-122.78548611,
-122.78547454,-121.78831019,-121.7624537,-119.5171875,-119.51571759,
-118.54518519,-118.54511574,-116.81631944,-116.6050463,-115.41570602,
-115.41196759,-114.53983796,-114.51606481,-112.65020833,-112.59722222,
-111.58196759,-111.58173611,-110.28418981,-108.88050926,-108.88037037,
-106.58741898,-106.58740741,-105.82334491,-105.61048611,-102.78446759,
-102.78175926,-101.92847222,-101.92841435,-99.70208333,-99.66606481,
-98.69592593,-98.69592014,-97.68861111,-96.54909722,-96.43082176,
-93.6450463,-93.64504051,-91.82571759,-91.82571181,-83.88231481,
-83.88003472,-82.53726852,-81.8415162,-81.78796296,-78.41912037,
-77.88599537,-77.88598958,-75.8,-75.79999421,-74.91194444,
-74.91193866,-70.52842593,-70.52751157,-66.66107639,-66.49625,
-64.62689815,-64.62497685,-63.84877315,-62.67493056,-62.67486111,
-56.45991898,-56.45849537,-55.80101852,-53.5209375,-53.42854167,
-51.79412037,-51.70625,-50.72030093,-50.72027778,-49.55359954,
-48.56030093,-48.52893519,-47.61050926,-47.61006944,-45.62118056,
-45.61965278,-43.70581019,-43.70578704,-42.61976852,-42.61907407,
-41.67361111,-41.64385417,-32.35585648,-31.6496875,-31.64862269,
-17.80746528,-17.77924769,-16.75157407,-16.75155093,-15.57109954,
-15.57106481,-14.64717593,-13.72175926,-13.67280093,-12.61773148,
-10.63041667,-10.63005787,-9.80740741,-9.80736111,-8.71253472,
-8.70666667,-6.74260417,-6.74258102,-5.34083333,-4.91016204,
-4.90943287,-2.30743056,-2.30638889,-0.42960648,-0.42840278]
y = [70.7572706,70.54032874,70.05606702,70.03624935,69.27432557,
69.27432117,68.43243561,68.22067996,67.78516637,67.64308661,
66.88118275,66.88062559,66.30052443,66.28947425,65.67543639,
64.90642245,64.90640759,63.66449628,63.60904412,63.14039473,
63.14022978,62.52515116,62.52499365,61.97652441,61.32001027,
61.32000308,60.68789985,60.57033966,60.00261623,60.00259097,
57.61865841,57.43806534,56.55456891,56.54383346,55.43956239,
55.43955595,50.38210045,44.53858607,43.50952278,43.50892299,
42.12805664,42.12802358,36.99275737,36.99274908,36.05906926,
36.05900272,33.41368763,33.41358922,32.27359692,27.70135708,
24.84323913,24.84254672,23.98532718,23.98459096,23.0642553,
23.0639276,22.5150554,22.51503233,22.08034126,22.08033742,
21.8389586,21.8389484,23.10692951,23.10771641,29.81761462,
29.81776653,31.21601939,31.21605924,32.68017101,33.03425222,
36.54083419,36.54092348,38.47670459,38.47672766,40.0590836,
40.05913083,43.0771602,43.07720928,45.35765585,49.31879272,
49.31952077,51.38303931,51.38309234,57.16432204,57.16437592,
58.92167454,61.46687347,61.46692457,65.24326265,65.24330938,
66.81838801,67.46953204,67.46964169,72.89983173,72.90644953,
74.08206155,75.44675245,75.44685685,76.74713302,76.77050437,
78.05420313,78.17438359,79.7183499,79.72118421,79.72429379,
79.91227229,79.91228745,80.99326008,81.04109716,81.20997602,
82.219385,82.41175016,82.49142149,83.49504942,83.49713412,
84.36266061,84.47724037,84.47833159,84.4859241,85.18879314,
85.19431565,86.18839601,86.18957211,86.32923784,87.17818962,
87.23249526,87.96788031,88.01785229,88.75344863,88.75424891,
89.51806878,89.51810973,89.91613619,89.91614411,90.73453049,
90.73474985,91.40125092,91.41664377,91.85156726,91.85279549,
92.34222988,92.38575227,92.75900826,92.75984105,92.59792734,
92.59772702,91.20024149,91.19975484,90.56381405,89.28641717,
89.28134229,87.14597333,87.14300865,85.15861765,85.15797276,
82.84855607,82.84738518,80.54827418,80.54825753,66.28762042,
63.00718054,63.00700893,54.31636812,54.18091963,51.84551574,
42.2968528,42.29683372,42.29509707,38.97123725,38.95998918,
30.75854662,30.75853234,28.19489508,28.19488261,21.31146526,
21.31063361,20.72423984,20.72422916,19.66675016,19.65459906,
19.30037669,19.30014055,18.82393793,18.82375279,18.89283954,
19.25883033,19.25883262,19.63216496,20.23324209,20.2332487,
24.12129249,24.12130103,25.03004562,25.03004973,25.76826801,
25.81806455,26.67629851,26.67631891,30.46561539,30.74262981,
30.74263179,30.91672453,30.92128596,31.30818311,31.3084222,
31.4588991,31.45890927,31.69236101,31.71975256,31.87221841,
31.87267866,31.9724062,31.97484795,32.10544092,32.10723373,
32.11864839,32.11864583,32.06417118,31.90691934,31.90689831,
31.39692865,31.3969252,31.14906127,31.07254683,29.76210069,
29.76059886,29.26593574,29.26590077,27.78880075,27.76287183,
27.0440895,27.04408511,26.26627309,25.36699318,25.27332511,
23.11069468,23.11069035,21.80609638,21.80609244,18.29594004,
18.295638,18.20182827,18.21706169,18.22000001,18.82965191,
18.98616378,18.98616554,19.69017271,19.6901748,20.01523736,
20.0152395,21.42764295,21.42784833,21.84871481,21.84950598,
21.78327154,21.78313985,21.72088105,21.59779516,21.59778708,
20.92961501,20.92955839,20.91266214,21.04288478,21.05619122,
21.41830913,21.44484473,21.79485625,21.79486561,22.3360831,
22.90340539,22.92289613,23.5358956,23.53620858,25.13688862,
25.13825808,27.00134805,27.00137215,28.16778118,28.16854978,
29.24170683,29.27634617,42.20507624,43.32162108,43.32331588,
68.1726824,68.22889458,70.29050421,70.29055095,72.69085058,
72.69092166,74.59109794,76.51130697,76.6133282,78.82157314,
83.02355351,83.0243163,84.77591304,84.77601173,87.11188547,
87.12441636,91.32441849,91.32446806,94.32811947,95.25177267,
95.25333675,100.83484899,100.83708178,104.85695,104.85952725]
w = [0.09462211,0.04377652,0.14838558,0.05943898,0.15541495,0.13085324,
0.062704,0.06243595,0.08839641,0.08066833,0.08655245,0.13400375,
0.12432887,0.09684014,0.08021506,0.1265312,0.05262315,0.06449225,
0.0758878,0.08259978,0.0806998,0.18695698,0.08123137,0.07486425,
0.12497271,0.10635125,0.15783934,0.08400718,0.24832489,0.12591398,
0.75945646,0.13893085,0.07963481,0.10749733,0.12091365,0.06358539,
0.01520488,0.03701155,0.16559939,0.21220943,0.08161835,0.16941486,
0.08949668,0.13363251,0.09692045,0.18369284,0.13672927,0.08379181,
0.01858722,0.01133573,0.06237293,0.24676197,0.10859054,0.12052321,
0.13203374,0.14501103,0.14774643,0.09328596,0.04971943,0.15257333,
0.28338405,0.09501884,0.98374631,0.05226721,0.09065792,0.13678137,
0.09321165,0.44103697,0.06999414,0.05989127,0.12692356,0.0915057,
0.11936501,0.10480617,0.1567755,0.07513431,0.07117161,0.06858016,
0.01640047,0.29806503,0.22542,0.12794823,0.21382192,0.80778319,
0.05041481,0.02423374,0.14427077,0.10418953,0.21508381,0.10940715,
0.04888315,0.04528401,0.04778175,0.11278799,0.43211842,0.03932949,
0.11803702,0.07236406,0.09973482,0.11787877,0.10316486,0.03396932,
0.07494178,0.0980055,0.15682156,0.39430807,0.2966579,0.0321651,
0.04839777,0.09632106,0.08455145,0.03593526,0.09416399,0.1499288,
0.20404766,0.05393556,0.05599547,0.08508938,0.03143724,0.03516901,
0.48995939,0.22142592,0.05018331,0.02789187,0.02197713,0.03036933,
0.20079765,0.0914527,0.04390079,0.0632086,0.12006129,0.04469976,
0.10379572,0.06173869,0.04413667,0.03245433,0.1633229,0.0436747,
0.06350709,0.05263706,0.04127021,0.04639606,0.06203611,0.0542154,
0.04355763,0.0831866,0.03767251,0.04846966,0.01901781,0.24288383,
0.05686747,0.0987101,0.11008607,0.0864383,0.17024615,0.23189691,
0.13231802,0.11141714,0.11234526,0.04201772,0.10555506,0.23622534,
0.15991181,0.07504075,0.08703826,0.078157,0.07949321,0.29557024,
0.0676124,0.16409294,0.24457436,0.10823184,0.14073518,0.35402206,
0.13634875,0.08048864,0.11152011,0.0714971,0.11998616,0.07697284,
0.08883651,0.08903601,0.12036493,0.07058305,0.01155317,0.08867653,
0.21117371,0.05630087,0.0809992,0.27670459,0.26026519,0.13855529,
0.15380278,0.23979833,0.20920358,0.1440551,0.13541747,0.1463744,
0.04642054,0.24201843,0.11214505,0.18320577,0.04986542,0.19388245,
0.07125025,0.22815885,0.08084224,0.06743765,0.28559653,0.11051846,
1.71124858,0.10948372,0.1427056,0.14208709,0.21579165,0.14818066,
0.10186744,0.02192575,0.07098707,0.09253821,0.13900954,0.12502331,
0.06113228,0.15379208,0.05778127,0.25567184,0.12133423,0.1361762,
0.06835819,0.17893468,0.07440845,0.05984869,0.02637486,0.06455977,
0.05552673,0.16468979,0.06516525,0.06218418,0.10451724,0.4187673,
0.08585429,0.02827772,0.19387362,0.0435158,0.02646894,0.16485791,
0.12165923,0.11332932,0.06376871,0.1044266,0.059728,0.14428556,
0.10856501,0.16783946,0.12808263,0.06199017,0.112075,0.04430589,
0.17411464,0.09521449,0.05556677,0.10710905,0.16484723,0.09197195,
0.09080481,0.11942555,0.29181033,0.05171834,0.10642797,0.0591445,
0.07264419,0.05472201,0.07241181,0.07863706,0.05298894,0.17034628,
0.13621438,0.12312648,0.20335133,0.10124627,0.08194233,0.08727886,
0.07454792,0.17554491,0.13723729,0.04581896,0.11138872,0.09357495,
0.09733723,0.21097312,0.05863559,0.02409536,0.11577836,0.08534116,
0.02837538,0.09877817,0.03943265,0.09397333,0.16018314,0.09669458,
0.18185679,0.11361261,0.07640622,0.0501189,0.1409333,0.04278513,
0.08166752,0.0946821,0.138107,0.05173292]
xrnd = np.rint(np.array(x)*25.)/25.
xrndv = xrnd[1:]
xrndv[np.flatnonzero(np.diff(xrnd)==0)]+=1./50.
xrndv[np.flatnonzero(np.diff(xrnd)==0)]+=1./100.
xs = np.unique(np.r_[x[0]+np.cumsum(np.repeat(np.diff(x)/4,4)),np.linspace(x[0], x[-1], len(x)*10)])
unweighted = CubicSmoothingSpline(x, y, smooth=5e-06)
weighted = CubicSmoothingSpline(x, y, weights=w, smooth=5e-06)
weightedimprovedx = CubicSmoothingSpline(xrnd, y, weights=w, smooth=5e-06)
def CubicSplineFromCubicSmoothingSpline(smoothing_spline, xrange=None, bc_type='natural', extrapolate=None):
# If using this to generate a periodic spline from a csaps spline, data is usually replicated
# Therefore restrict the xrange to the actual period to be modelled
x = smoothing_spline.spline.breaks
y3 = smoothing_spline.spline.coeffs[0,:]*6
if xrange:
assert xrange[0] < xrange[1]
xminidx = max(0,np.flatnonzero(np.r_[xrange[0],x]<=xrange[0])[-1]-1)
xmaxidx = min(x.size-1,np.flatnonzero(np.r_[x,xrange[1]]>=xrange[1])[0])
x = x[xminidx:xmaxidx+1].copy()
x[0]=max(xrange[0],x[0])
x[-1]=min(xrange[1],x[-1])
y3 = y3[xminidx:xmaxidx+1]
idxs_to_use = [0,x.size-1]
idx_before_zero_crossings = np.where(np.diff(np.sign(y3)))[0]
idxs_to_use.extend(idx_before_zero_crossings.tolist())
for aidx,bidx in zip(np.r_[0,idx_before_zero_crossings],np.r_[idx_before_zero_crossings,x.size-1]):
idx = np.argmax(np.abs(y3[aidx:bidx+1]))+aidx
idxs_to_use.append(idx)
x_compressed = np.unique(x[idxs_to_use])
y_compressed = smoothing_spline(x_compressed)
if bc_type=='periodic':
y_compressed[0] = y_compressed[-1] = np.mean(y_compressed[[0,-1]])
return CubicSpline(x_compressed, y_compressed, bc_type=bc_type, extrapolate=extrapolate)
compressedspline = CubicSplineFromCubicSmoothingSpline(weighted)
plt.plot(xs, unweighted(xs), '-', xs, weighted(xs), '-', xs, weightedimprovedx(xs), '-', xs, compressedspline(xs), '-', x, y, 'o')
plt.show()
for nu in range(1,4):
fig,(ax1,ax2,ax3,ax4)=plt.subplots(1, 4, figsize=(12,4))
ax1.plot(xs, unweighted(xs,nu=nu), '-')
ax1.title.set_text('unweighted nu='+str(nu))
ax2.plot(xs, weighted(xs,nu=nu), '-')
ax2.title.set_text('weighted nu='+str(nu))
ax3.plot(xs, weightedimprovedx(xs,nu=nu), '-')
ax3.title.set_text('weighted, improved x nu='+str(nu))
ax4.plot(xs, compressedspline(xs,nu=nu), '-')
ax4.title.set_text('compressed spline nu='+str(nu))
plt.show()