7

scipy UnivariateSpline does not allow multivalued X. I read that this has been changed, but does not seem to work me. I am using the latest version, having just used pip to try to download, which says that I have the latest.

I have tried changing s (smoothing) from 0 and None (which is defined as X must be strictly increasing), but this doesn't fix the problem.

import matplotlib.pyplot as plt
from scipy.interpolate import UnivariateSpline

x=[152,152,152,152,152,159,159,159,159,159,166,166,166,166,166,174,174,174,174,174,181,181,181,181,181,188,188,188,188,188,194,194,194,194,194,202,202,202,202,202,208,208,208,208,208,215,215,215,215,215,222,222,222,222,222,229,229,229,229,229,236,236,236,236,236,243,243,243,243,243,250,250,250,250,250,258,258,258,258]

y=[-1.31639523,-1.90045889,-1.81769285,-1.25702203,-1.31975784,-0.76206863,-0.74170737,-0.66029284,-0.58124809,-0.49593701,-0.19309943,0.02254396,-0.04614866,0.06709774,0.10436002,0.577175,0.56809403,0.89547559,0.60922195,0.76220672,1.0461253,1.1304339,1.56360338,1.34189828,1.41658105,1.98677786,2.40487089,2.20431052,1.91072699,2.49328809,2.670556,2.85024397,3.24333426,2.44841554,3.14604703,3.39128172,3.78063788,3.21446612,3.07158159,3.79503965,3.40717945,4.02417242,3.70708767,4.00729682,4.25504517,4.28874564,3.9356614,4.30337567,4.02388633,4.65376986,4.33884509,4.68839858,4.10508666,4.26236997,4.53098529,5.03443645,4.07940011,4.3033351,4.43476139,4.80221614,4.49558967,4.5052504,4.40289487,5.15433152,5.1330299,4.30299696,4.47974301,5.34886789,4.60896298,5.35997675,4.40204983,5.50162549,4.3056854,4.87120463,5.36265274,4.33578634,5.06347439,4.46811258,5.30920785]

s = 0.1 # set smoothing to non-zero
spl = UnivariateSpline(x, y, s=s)

I get this error message :- spl = UnivariateSpline(x, y, s=s) File "C:\Python37\lib\site-packages\scipy\interpolate\fitpack2.py", line 177, in __init__ raise ValueError('x must be strictly increasing') ValueError: x must be strictly increasing.

Any help or advice would be most welcomed!

A. Nadjar
  • 2,440
  • 2
  • 19
  • 20
itpme
  • 131
  • 1
  • 1
  • 6

2 Answers2

5

Got it! After many hours looking at code I found a link https://github.com/kawache/Python-B-spline-examples that gave me a clue, and I can now produce results similar to those from my original FORTRAN code (which was written using M.G. Cox original code 1, and subsequently modified to Cox & de Boor 2).

Maybe I should write it up as "Spline fitting to data of multiple observations at successive irregular points in time".

Thank for all the help with this.

Here is my code :-

import matplotlib.pyplot as plt
from scipy import interpolate
import numpy as np

x=[152.0,152,152,152,152,159,159,159,159,159,166,166,166,166,166,174,174,174,174,174,181,181,181,181,181,188,188,188,188,188,194,194,194,194,194,202,202,202,202,202,208,208,208,208,208,215,215,215,215,215,222,222,222,222,222,229,229,229,229,229,236,236,236,236,236,243,243,243,243,243,250,250,250,250,250,258,258,258,258]

y=[-1.31639523,-1.90045889,-1.81769285,-1.25702203,-1.31975784,-0.76206863,-0.74170737,-0.66029284,-0.58124809,-0.49593701,-0.19309943,0.02254396,-0.04614866,0.06709774,0.10436002,0.577175,0.56809403,0.89547559,0.60922195,0.76220672,1.0461253,1.1304339,1.56360338,1.34189828,1.41658105,1.98677786,2.40487089,2.20431052,1.91072699,2.49328809,2.670556,2.85024397,3.24333426,2.44841554,3.14604703,3.39128172,3.78063788,3.21446612,3.07158159,3.79503965,3.40717945,4.02417242,3.70708767,4.00729682,4.25504517,4.28874564,3.9356614,4.30337567,4.02388633,4.65376986,4.33884509,4.68839858,4.10508666,4.26236997,4.53098529,5.03443645,4.07940011,4.3033351,4.43476139,4.80221614,4.49558967,4.5052504,4.40289487,5.15433152,5.1330299,4.30299696,4.47974301,5.34886789,4.60896298,5.35997675,4.40204983,5.50162549,4.3056854,4.87120463,5.36265274,4.33578634,5.06347439,4.46811258,5.30920785]

plt.plot(x, y, 'ro', ms=5)

tck,u = interpolate.splprep([x,y],k=3,s=32)

u=np.linspace(0,1,num=50,endpoint=True)
out = interpolate.splev(u,tck)

plt.plot(x, y, 'ro', out[0], out[1], 'b' )

plt.show()

and the result (followed by the plot of the original spline from Cox 1 and de Boor 2).

1: M. G. Cox, “The numerical evaluation of b-splines”, J. Inst. Maths Applics, 10, p.134-149, 1972.

2: C. de Boor, “On calculating with b-splines”, J. Approximation Theory, 6, p.50-62, 1972. Plot of results from python code. Plot of reults from original Fortran code from Cox & De Boor

itpme
  • 131
  • 1
  • 1
  • 6
0

This won't work with your data set. It needs a contiuosly increasing x variable in order to do the interpolation. This is a requirement for the implementation.

  • You can edit the data set to remove the duplicate x values and it will work. Alternatively you can try the approach below which is much more involved.

This answer by @xdze2 goes through the alternative method to smooth a curve using the individual coordinates.

fit a spline separately on each coordinates of the given curve

bamdan
  • 836
  • 7
  • 21
  • Thanks Bamdan, as you note, I have tried the latest version to no avail. The article that I read was the link you have given. I'm not sure that it is a bug - maybe a "feature"! In which case I do not know what to try - any help would be appreciated. – itpme Aug 24 '19 at 11:28
  • Ah ok, sorry that was no help. I’ll have a look later and let you know. Seems to be a number of optimize methods affected by the same issue. Thanks – bamdan Aug 24 '19 at 11:34
  • Thanks A. Nadjar for reformatting the question for me - I need to learn how to do this! – itpme Aug 24 '19 at 15:42
  • 1
    This looks like a restriction in the software, and I don't think it is a mathematical requirement. It may be a problem when using ALL the points in X as knots, but not when there are fewer knots than unique values in X. See De Boor's algorithms (which incidentally work with my data) and allow smoothing, so I am surprised that the scipy routines won't work. There appears to be no problem in R where FITPACK is used. I may try using the mean of all the Y values at each point in X, and adjust the weights according to the (maxcount-count) at each X. Thanks for your help. – itpme Aug 24 '19 at 21:43
  • No worries, it’s a bit annoying alright. I was not entirely familiar with how it worked under the hood but it’s an interesting area. I guess the implementation is optimised for speed and this particular optimiser probably wouldn’t be performant if allowing any x. I’ve amended the answer to point to the implementations requirement. Can you accept? – bamdan Aug 25 '19 at 06:08
  • I need to do a lot more work on this to find a solution. As I say, I can use the De Boor algorithms in FORTRAN, but they are not so elegant as Python. I accept the answer you have offered, and will post any further problems(!). Many thanks for your help. – itpme Aug 25 '19 at 16:30
  • Have you seen https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.interpolate.BSpline.html#scipy.interpolate.BSpline. Would it this be of use in this case? – bamdan Aug 26 '19 at 12:18
  • I haven't had time to do much more on this yet, but thanks for the link, which I had seen, and will try again. It appears that the routines described accept multiple values in X (the knot positions) where the knots are at every point in X. More work needed by me !!!! Many thanks. – itpme Aug 26 '19 at 16:49