Reputation: 1363
I have a sparse data set, f44
, made up of bearings in degrees and ssi (dbm) values:
ssi
deg
4.0 -69
59.0 -73
162.0 -73
267.0 -61
319.0 -75
I reindexed f44
to include all the missing indices from 0-359:
f44i = f44.reindex(np.arange(0,360))
When I interpolate (using quadratic) and plot the figure, it's apparent that the result doesn't interpolate between the first/lowest bearing and the highest:
f44i = f44i.interpolate(method='quadratic')
f44i.plot()
How can I interpolate this data in a way that will fill in between 0 and 360 degrees? The pandas Series.interpolate
documentation does not appear to have anything built-in, nor does the scipy
documentation.
Upvotes: 0
Views: 1664
Reputation: 1363
I'm not convinced this is the best way to do this, but it seems to work. Please add something if there is a better way.
Since I'm only interested in 0-360 degrees, I can duplicate the dataset from -360-0, and 360-720, expanding my original data set to the left and right, like so:
import numpy as np
# Create left side
f44il = f44i.copy()
f44il.index = np.arange(-360,0)
# Create right side
f44ir = f44i.copy()
f44ir.index = np.arange(360,720)
Interpolating and plotting the result looks promising (the third command shows 0-360 in a different color):
f44expanded = pd.concat([f44il, f44i, f44ir]).interpolate(method='quadratic')
f44expanded.plot()
f44expanded[np.arange(0,360)].plot()
Then I can just create a new series from the interpolated data with an index from 0-360, which looks like it gives me exactly what I want:
f44final = f44expanded[np.arange(0,360)]
f44final.plot()
I suspect there is a better way to do this, so feel free to add an answer if you know of one.
Upvotes: 0
Reputation:
I have an alternative approach to this problem using scipy
to interpolate onto a closed curve. First, I converted your data from (deg, ssi) to psuedo cartesian coordinates (x,y) assuming deg
is the polar angle and ssi
is the (negative) of the radial distance. Then you can use the method defined here to interpolate a closed curve onto a set of (x,y) points.
import numpy as np
import pandas
import matplotlib.pyplot as plt
from scipy import interpolate
dic = {'deg': [4.0, 59.0, 162.0, 267.0, 319.0],
'ssi': [-69, -73, -73, -61, -75]}
f44 = pandas.DataFrame(data=dic)
'''
Now, lets do the following. Convert your data from (deg, ssi) to (x,y)
where x = ssi* cosd(deg), y=ssi*sind(deg). Now we need to interpolate a closed
curve onto these set of cartesian points.
'''
f44['x'] = -f44['ssi']*np.cos( np.deg2rad(f44['deg']))
f44['y'] = -f44['ssi']*np.sin( np.deg2rad(f44['deg']))
x = f44.as_matrix(columns=[f44.columns[2]])[:,0]
y = f44.as_matrix(columns=[f44.columns[3]])[:,0]
x = np.r_[x, x[0]]
y = np.r_[y, y[0]]
tck, u = interpolate.splprep([x, y], s=0, per=True)
xi, yi = interpolate.splev(np.linspace(0, 1, 1000), tck)
# Save interpolated data to new dataframe.
f44i = pandas.DataFrame(data = {'x':xi, 'y':yi})
f44i['deg'] = np.rad2deg( np.arctan2(f44i['y'],f44i['x']))
f44i['ssi'] =-np.sqrt( f44i['x']**2 + f44i['y']**2)
for i,l in enumerate(f44i['deg']):
if l < 0:
f44i['deg'][i] = 360 + f44i['deg'][i]
fig, ax = plt.subplots(1, 1)
ax.plot(f44i['deg'], f44i['ssi'], '.', markersize=0.5)
ax.plot(f44['deg'], f44['ssi'], '.', color='red')
plt.show()
Now we get a curve that looks like the one below. (re-converted from the psuedo cartesian coordinates to your preferred (deg, ssi) coordinates). Also, I have created a new dataframe to replace the f44i
you created. You can make this code more suitable for your specific application.
Upvotes: 1