Camille G.
Camille G.

Reputation: 23

How to interpolate a curve with irregular scale?

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:

enter image description here

I've been trying to smooth the curve like Excel does. I've tried using interp1d (all methods), spline, Akima1DInterpolator.

Upvotes: 2

Views: 827

Answers (1)

mikuszefski
mikuszefski

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()  

Interpolation In blue the original data, in orange the smooth interpolation.

Upvotes: 1

Related Questions