pythonnumpymathscipyinterpolation

Interpolating a array that has many zeros outputs wrong result


Im trying to interpolate a set of x coordinates to y coordinates.

x are the points Im trying to find a y for. The points I know are: xp (x coordinates) and their respective fp (y coordinates).

The problem is that when I run the code, y is the number 0.97610476 repeated 33 times. Which is of course not the right answer.

I belive the problem rises when about 70% of the first numbers in the x and xp arrays are zero, maybe the numpy function np.interp takes all numbers in the array into consideration to estimate the y values, oposed to what would be done with a calculator or on paper, where you take only the values between the value you want into the calculation.

Here is the code with the arrays:

import numpy as np

x = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.007705615446897033,
 -0.007705615446897033, -0.05709260606658533, -0.05709260606658533,
 -0.12137136703522947, -0.12137136703522947, -0.1535107475195779,
 -0.1535107475195779, -0.18565012800417238, -0.18565012800417238])

xp = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
 0.0, -1.34689e-06, -0.000273863136, -0.001326340329, -0.00287521918,
 -0.004941795493, -0.007555995729, -0.01071049581, -0.01439643971,
 -0.018603479056, -0.02331980126, -0.028531366613, -0.034172728629,
 -0.040283876545, -0.046985078741, -0.053797694609, -0.060610310434,
 -0.067422926258, -0.07423554208, -0.081048157901, -0.087860773721,
 -0.09467338954, -0.101486005358, -0.108298621175, -0.115111236993,
 -0.12192385281, -0.128736468628, -0.135549084446, -0.142361700265,
 -0.149174316084, -0.155986931905, -0.162799547727, -0.16961216355,
 -0.176424779375, -0.183237395203, -0.190050011032, -0.196862626864,
 -0.203675242698, -0.210487858535, -0.217300474376])

fp = np.array([0.0, 0.010598548767, 0.021197097534, 0.031795646301, 0.042394195067,
 0.052992743834, 0.063591292601, 0.074189841368, 0.084788390135,
 0.095386938902, 0.105985487669, 0.116584036435, 0.127182585202,
 0.137781133969, 0.148379682736, 0.158978231503, 0.16957678027,
 0.180175329037, 0.190773877804, 0.20137242657, 0.211970975337,
 0.222569524104, 0.233168072871, 0.243766621638, 0.254365170405,
 0.264963719172, 0.275562267938, 0.286160816705, 0.296759365472,
 0.307357914239, 0.317956463006, 0.328555011773, 0.33915356054,
 0.349752109306, 0.360350658073, 0.37094920684, 0.381547755607,
 0.392146304374, 0.402744853141, 0.413343401908, 0.423941950675,
 0.434540499441, 0.445139048208, 0.455737596975, 0.466336145742,
 0.476934694509, 0.487533243276, 0.498131792043, 0.508730340809,
 0.519328889576, 0.529927438343, 0.54052598711, 0.551124535877,
 0.561723084644, 0.572321633411, 0.582920182177, 0.593518730944,
 0.604117279711, 0.614715828478, 0.625314377246, 0.635912926032,
 0.646511474256, 0.657104739543, 0.667649141654, 0.678133049978,
 0.688526896259, 0.698796708974, 0.708913631472, 0.718849263002,
 0.728575709565, 0.738065661756, 0.74729295673, 0.756264519149,
 0.764920687899, 0.773130776065, 0.781249735501, 0.789368694886,
 0.797487654269, 0.80560661365, 0.813725573029, 0.821844532407,
 0.829963491784, 0.838082451161, 0.846201410536, 0.854320369912,
 0.862439329287, 0.870558288663, 0.878677248039, 0.886796207416,
 0.894915166794, 0.903034126173, 0.911153085554, 0.919272044936,
 0.927391004321, 0.935509963708, 0.943628923097, 0.95174788249,
 0.959866841886, 0.967985801285, 0.976104760687])

y = np.interp(x, xp, fp)

print(len(y))

I didn't tried many other alternatives. I tried using scipy interp1d() function, but that resulted the same problem.

I don't expect theres much more to do about this, maybe I will have to create a "manual" interpolation function.


Solution

  • If you look at the docs np.interp requires "One-dimensional linear interpolation for monotonically increasing sample points."

    Your data is actually monotically decreasing and the x values are negative. If we change the sign of x then the data reflects on the y axis and become monotically incresing.

    You can also filter the points where x is 0 if you want (In order to really be a function, x values need be unique) In the code I filtered the values of x that are 0.

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.007705615446897033,
     -0.007705615446897033, -0.05709260606658533, -0.05709260606658533,
     -0.12137136703522947, -0.12137136703522947, -0.1535107475195779,
     -0.1535107475195779, -0.18565012800417238, -0.18565012800417238])
    
    xp = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
     0.0, -1.34689e-06, -0.000273863136, -0.001326340329, -0.00287521918,
     -0.004941795493, -0.007555995729, -0.01071049581, -0.01439643971,
     -0.018603479056, -0.02331980126, -0.028531366613, -0.034172728629,
     -0.040283876545, -0.046985078741, -0.053797694609, -0.060610310434,
     -0.067422926258, -0.07423554208, -0.081048157901, -0.087860773721,
     -0.09467338954, -0.101486005358, -0.108298621175, -0.115111236993,
     -0.12192385281, -0.128736468628, -0.135549084446, -0.142361700265,
     -0.149174316084, -0.155986931905, -0.162799547727, -0.16961216355,
     -0.176424779375, -0.183237395203, -0.190050011032, -0.196862626864,
     -0.203675242698, -0.210487858535, -0.217300474376])
    
    fp = np.array([0.0, 0.010598548767, 0.021197097534, 0.031795646301, 0.042394195067,
     0.052992743834, 0.063591292601, 0.074189841368, 0.084788390135,
     0.095386938902, 0.105985487669, 0.116584036435, 0.127182585202,
     0.137781133969, 0.148379682736, 0.158978231503, 0.16957678027,
     0.180175329037, 0.190773877804, 0.20137242657, 0.211970975337,
     0.222569524104, 0.233168072871, 0.243766621638, 0.254365170405,
     0.264963719172, 0.275562267938, 0.286160816705, 0.296759365472,
     0.307357914239, 0.317956463006, 0.328555011773, 0.33915356054,
     0.349752109306, 0.360350658073, 0.37094920684, 0.381547755607,
     0.392146304374, 0.402744853141, 0.413343401908, 0.423941950675,
     0.434540499441, 0.445139048208, 0.455737596975, 0.466336145742,
     0.476934694509, 0.487533243276, 0.498131792043, 0.508730340809,
     0.519328889576, 0.529927438343, 0.54052598711, 0.551124535877,
     0.561723084644, 0.572321633411, 0.582920182177, 0.593518730944,
     0.604117279711, 0.614715828478, 0.625314377246, 0.635912926032,
     0.646511474256, 0.657104739543, 0.667649141654, 0.678133049978,
     0.688526896259, 0.698796708974, 0.708913631472, 0.718849263002,
     0.728575709565, 0.738065661756, 0.74729295673, 0.756264519149,
     0.764920687899, 0.773130776065, 0.781249735501, 0.789368694886,
     0.797487654269, 0.80560661365, 0.813725573029, 0.821844532407,
     0.829963491784, 0.838082451161, 0.846201410536, 0.854320369912,
     0.862439329287, 0.870558288663, 0.878677248039, 0.886796207416,
     0.894915166794, 0.903034126173, 0.911153085554, 0.919272044936,
     0.927391004321, 0.935509963708, 0.943628923097, 0.95174788249,
     0.959866841886, 0.967985801285, 0.976104760687])
    
    # filter zero values
    x=x[x<0]
    fp=fp[xp<0]
    xp=xp[xp<0]
    
    # just take the negative of x and xp to mirror it in the y axis
    y = np.interp(-x, -xp, fp)
    
    plt.plot(xp,fp,'x')
    plt.plot(x,y,'x')
    
    
    print(y)
    
    plt.show()
    
    
    
    [0.69927656 0.69927656 0.78517646 0.78517646 0.8617809  0.8617809
     0.90008312 0.90008312 0.93838535 0.93838535]
    

    enter image description here