По-видимому, большие различия в одномерной сплайн-интерполяции данных

Я пытаюсь создать одномерную сплайн-интерполяцию в python, чтобы соответствовать большому набору данных, и когда я рисую два, кажется, что есть большие различия. Я пытался установить коэффициент сглаживания на множество разных значений (включая ноль, поэтому он должен проходить через каждую точку данных), но когда я рисую два, я получаю большие различия.

##
# Univariate Spline Interpolation
##

## This function interpolates the data by creating multiple times the amount of points in the data set and fitting a spline to it
## Input:
# dataX - X axis that you corresponds to dataset
# dataY - Y axis of data to fit spline on (must be same size as dataX)
# multiple - the multiplication factor, default is 2 ( <1 - Less points, 1 - same amount of points, >1 - more points)
# order - order of spline, default is 4 (3 - Cubic, 4 - Quartic)
## Output
# splinedDataX - splined X Axis
# splinedDataY - splined Y Axis

def univariate_spline_interpolation( dataX, dataY, multiple=2, order=4):

    #Libraries
    from numpy import linspace,exp
    from numpy.random import randn
    import matplotlib.pyplot as plt
    from scipy.interpolate import UnivariateSpline, LSQUnivariateSpline


    #Find sizes of x and y axis for comparison and multiple
    sizeX = len(dataX)
    sizeY = len(dataY)


    #Error catching
    if(sizeX != sizeY):
        print "Data X axis and Y axis must have same size"
        return

    if(multiple <= 0):
        print "Order must be greater than 0"
        return

    if(order < 1 or order >5):
        print "Order must be 1 <= order <= 5"
        return

    #Create Spline
    s = UnivariateSpline(dataX, dataY, k=3, s=0)   
    # s is smoothing factor so spline doesn't shoot off in between data points
    #Positive smoothing factor used to choose the number of knots.
    #Number of knots will be increased until the smoothing condition is satisfied:
    # sum((w[i]*(y[i]-s(x[i])))**2,axis=0) <= s
    #If None (default), s=len(w) which should be a good value if 1/w[i] is an estimate of the standard deviation of y[i].
    #If 0, spline will interpolate through all data points.

    #Create new axis based on numPoints
    numPoints = sizeX * multiple   #Find mumber of points for spline
    startPt = dataX[1]   #find value of first point on x axis
    endPt = dataX[-1]   #find value of last point on x axis
    splinedDataX = linspace(startPt, endPt, numPoints)   #create evenly spaced points on axis based on start, end, and number of desired data points

    #Create Y axis of splined Data
    splinedDataY = s(splinedDataX)   #Create new Y axis with numPoints etnries of data splined to fit the original data

    return splinedDataX, splinedDataY

##
# Text Cubic Spline
##

splinedX, splinedY = univariate_spline_interpolation(sensorTimestamp, filteredData[1], multiple=1)

print "old x data"
print "length", len(sensorTimestamp)
print "Starts", sensorTimestamp[0]
print "Ends", sensorTimestamp[-1]
print ""

print "new x data"
print "length", len(splinedX)
print "multiple", len(splinedX)/len(filteredData[1])
print "Starts", splinedX[0]
print "Ends", splinedX[-1]
print ""

print "old y data"
print "length", len(filteredData[1])
print "Starts", filteredData[1][0]
print "Ends", filteredData[1][-1]
print ""

print "new y data"
print "length", len(splinedY)
print "Starts", splinedY[0]
print "Ends", splinedY[-1]


difference = []
for i in splinedY:
    difference.append(splinedY[i] - filteredData[1][i])

plt.figure(figsize=(20,3))
plt.plot(sensorTimestamp, filteredData[1], label='Non-Splined', marker='*')
plt.plot(splinedX, splinedY, label='Splined')
plt.plot(sensorTimestamp, difference, label='Difference', ls='--')
plt.title(' BW Filtered Data from LED 1')
plt.axis([19, 30, -300, 300])
plt.legend(loc='best')
plt.show()

Выходная печать:

old x data
length 14690
Starts 0.0
Ends 497.178565979

new x data
length 14690
multiple 1.0
Starts 0.0555429458618
Ends 497.178565979

old y data
length 14690
Starts 50.2707843894
Ends 341.661410048

new y data
length 14690
Starts 416.803282313
Ends 341.661410048

Выходной график

Как вы можете видеть, различия огромны, но на графике данные кажутся точно такими же точками (или очень близкими).


person user3123955    schedule 26.08.2014    source источник


Ответы (2)


Кажется, что когда вы вычисляете разницу с

splinedY[i] - filteredData[1][i]

данные неправильно выровнены по оси x, и поэтому вы вычитаете значения, которые не лежат в одной и той же точке оси x. В сплайновых данных временные метки немного смещены вправо, потому что в функции univariate_spline_interpolation

startPt = dataX[1]

в то время как количество точек такое же, как и во входных данных x. Эту строку, вероятно, следует изменить на

startPt = dataX[0]
person Deve    schedule 27.08.2014
comment
Проблема сохраняется (только разница немного смещена), когда я изменил строку на dataX[0]. - person user3123955; 27.08.2014

Я думаю, что вычисление разницы на

splinedY[i] - отфильтрованные данные[1][i]

принципиально сомнительно. 'splinedY[i]' вычисляются из равномерно распределенных значений X (splinedDataX) в univariate_spline_interpolation(). SplinedDataX не будет таким же, как 'sensorTimestamp'; поэтому сравнение их соответствующих значений Y не имеет смысла.

После поиска в Google о том, как цикл for должен быть закодирован в python, я думаю, что виновник проблемы находится в утверждении

для i в splinedY:

«i» в этом операторе будет значением элемента массива, а не индексом. Правильный синтаксис будет

для i в диапазоне (len (splinedY)):

person fang    schedule 27.08.2014
comment
Хм, я никогда не думал об этом. Но соседние точки данных находятся рядом, почему такие огромные различия? - person user3123955; 27.08.2014
comment
Я не знаком с Питоном. Но уверены ли вы, что i' вместо i в splinedY действительно означает индекс массива, а не фактическое значение элемента массива? - person fang; 28.08.2014
comment
вы правы, я должен использовать for indx, val in enumerate(splinedY), что теперь приводит к гораздо меньшим отклонениям, но они все еще огромны по сравнению с тем, что должно быть - person user3123955; 28.08.2014
comment
@OP: Возможно, вы захотите опубликовать новый результат (числовые данные и график), чтобы люди могли помочь. - person fang; 28.08.2014
comment
@user3123955 user3123955 ... и, возможно, куда-нибудь сбросить ваши входные данные (pastbin или около того) и опубликовать ссылку, чтобы мы могли опробовать ваш код. - person Deve; 28.08.2014