Seite 1 von 1

Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Dienstag 21. September 2010, 10:56
von StanKitz
Suche einen geeignete numpy/Scipy Methode zum Interpolieren von nicht gesetzten Werten (np.NaN) in einem 2D-Numpy array. Scipy interp2D liefert leider NaN auf dem ganzen Ergebnisarray sobald ein einzelner Wert des Eingagsarrays auf NaN gesetzt wird. Stattdessen sollte die Funktion eigentlich den Wert "8" auf der nicht gesetzten Zelle interpolieren.
Hat jemand eine Idee ?
Gibt es evtl. andere Lösungen, z.B. über MatPlotLib oder image ?

Hier ist mein Code auf der Basis von interp2D :

Code: Alles auswählen

    import numpy as np
    from scipy import interpolate
    
    vX = np.linspace(-5, 5, 11)
    vY = vX
    vvX, vvY = np.meshgrid(vX, vY)
    vvZ = 10 + vvX + vvY # init all valid data

    vvZ[4, 4] = np.NaN # set single cell to not measured  -> causes NaN in interpolated matrix vvZnew !!!
    
    """
    vvZ
    array([[  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.],
           [  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.],
           [  2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.],
           [  3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.],
           [  4.,   5.,   6.,   7.,  NaN,   9.,  10.,  11.,  12.,  13.,  14.],
           [  5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.],
           [  6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.],
           [  7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.],
           [  8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.],
           [  9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.],
           [ 10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.]])    
    """
    
    #vvZmasked=np.ma.masked_invalid(vvZ) # masking does not help   
    myFunc = interpolate.interp2d(vX, vY, vvZ, kind='linear')

    vXnew = np.linspace(-5, 5, 11) # keep original grid
    #vXnew = np.linspace(-5, 5, 21) # expand original grid
    vYnew = vXnew
    
    # Returns the cross product
    vvZnew = np.round(myFunc(vXnew, vYnew)) # interpolated z array

    print vvZ
    print vvZnew
    
    """
    vvZnew
    [[ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]
     [ NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN]]    
    """

Re: Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Mittwoch 22. September 2010, 10:20
von mkesper
Nach etwas Stöbern vermute ich, dass du masked Arrays benutzen müsstest.
Nachtrag: Es wäre toll, wenn die Doku zu scipy und numpy auch als HTML vorliegen würde, das durchsucht sich einfach besser!

Re: Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Mittwoch 22. September 2010, 15:24
von StanKitz
Danke für den Hinweis, aber hatte ich auch schon ausprobiert. Habe inzwischen eine ähnliche Frage auf der Scipy-user mailing list gefunden, allerdings ohne konkrete Lösung - scheint also kein ganz einfaches Problem zu sein. :K
Bzgl. der Numpy/Scipy Doku: Ich verwende meist die Online-Hilfe auf der Scipy-Seite, dort findet man recht schnell was man sucht über Search-Felder oder inhaltliche und alphabetische Listen.

Re: Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Mittwoch 22. September 2010, 17:55
von DaMutz
du könntest mit der 'numpy.nan_to_num(x)' Funktion das NaN durch 0 ersetzen.

Code: Alles auswählen

>>> x = np.array([np.inf, -np.inf, np.nan, -128, 128])
>>> np.nan_to_num(x)
array([  1.79769313e+308,  -1.79769313e+308,   0.00000000e+000,
        -1.28000000e+002,   1.28000000e+002])

Re: Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Mittwoch 22. September 2010, 19:09
von gkuhl
Vielleicht hilft dir das folgende weiter:

Code: Alles auswählen

In [86]: A
Out[86]: 
array([[  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.],
       [  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.],
       [  2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.],
       [  3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.],
       [  4.,   5.,   6.,   7.,  NaN,   9.,  10.,  11.,  12.,  13.,  14.],
       [  5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.],
       [  6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.],
       [  7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.],
       [  8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.],
       [  9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.],
       [ 10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.]])

In [87]: n,m = A.shape

In [88]: x,y = mgrid[0:n,0:m]

In [89]: mask = ~isnan(A)

In [90]: interp = interpolate.interp2d(x[mask], y[mask], A[mask])
Warning:     No more knots can be added because the number of B-spline coefficients
    already exceeds the number of data points m. Probably causes: either
    s or m too small. (fp>s)
    kx,ky=1,1 nx,ny=15,12 m=120 fp=0.000000 s=0.000000

In [91]: xn,yn = arange(n), arange(m)

In [92]: interp(xn,yn).round()
Out[92]: 
array([[ -0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.],
       [  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.],
       [  2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.],
       [  3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.],
       [  4.,   5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.],
       [  5.,   6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.],
       [  6.,   7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.],
       [  7.,   8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.],
       [  8.,   9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.],
       [  9.,  10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.],
       [ 10.,  11.,  12.,  13.,  14.,  15.,  16.,  17.,  18.,  19.,  20.]])
Grüße
Gerrit

Re: Interpolation von NaN-Zellen in 2D-Matrix

Verfasst: Mittwoch 22. September 2010, 21:23
von StanKitz
Vielen Dank, die von gkuhl vorgeschlagene mask-Methode funktioniert wunderbar selbst für größere zusammenhängene NaN-Bereiche. Die Ergebnisse liegen näher an den ganzen Zahlen (im Beispiel) wenn man das kwarg kind='quintic' oder kind='cubic' setzt statt den Defaultwert kind='linear' zu benutzen.
Ich hatte es bislang nur mit numpy.maskedArrays versucht was nicht funktionierte.