Reputation: 23
I have the following granulometric data that I want to show on a graph, where x is the grain size and y, the probability density function. x follows a geometric sequence (each value multiplied by 2)
x: [0.0, 0.078130000000000005, 0.15626000000000001, 0.31252000000000002, 0.62504000000000004, 1.2500800000000001, 2.5001600000000002, 5.0003200000000003, 10.000640000000001, 20.001280000000001]
y: [0.0, 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
Here is the graph:
I've been trying to smooth the curve like Excel does. I've tried using interp1d (all methods), spline, Akima1DInterpolator.
Upvotes: 2
Views: 827
Reputation: 4043
So in my comment above I said easily. The problem, however, is the fact that the data is very flat at the end. Cubic and higher order interpolation do not like flat data. They tend to oscillate. The trick would be, as mentioned by @f5r5e5d, to rescale the data in such a way that the flat part becomes very short. In this case a double-log-scale seems OK. Unfortunately, this does not work with y = 0
values. Hence, either one has to remove this value or choose a reasonable small value for it (but not too small as on a double-log-scale that point would drift off).
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
xList = [0.078130000000000005, 0.15626000000000001, 0.31252000000000002, 0.62504000000000004, 1.2500800000000001, 2.5001600000000002, 5.0003200000000003, 10.000640000000001, 20.001280000000001]
yList = [ 1.0512499897262986, 0.8764973224043381, 0.6221799472771921, 0.3760124741123981, 0.19346808043817057, 0.08474951460350254, 0.0316071940839253, 0.010035880788326037, 0.0]
yList[-1] = 1.e-5 ###manually put a value for the zero
xLogList = [ np.log( x ) for x in xList ]
yLogList = [ np.log( y ) for y in yList ]
f = interp1d(xLogList, yLogList, kind='cubic')
xInterLogList = np.linspace( np.log( xList[0] ), np.log( xList[-1] ), 100 )
yInterLogList = [ f( x ) for x in xInterLogList ]
fig1=plt.figure()
ax=fig1.add_subplot( 1, 1, 1 )
ax.plot(xList, yList)
ax.plot( [ np.exp( x ) for x in xInterLogList ], [ np.exp( y ) for y in yInterLogList ] )
plt.show()
In blue the original data, in orange the smooth interpolation.
Upvotes: 1