Wandle den Nanowert in Null um


88

Ich habe ein 2D-Numpy-Array. Einige der Werte in diesem Array sind NaN. Ich möchte bestimmte Operationen mit diesem Array ausführen. Betrachten Sie zum Beispiel das Array:

[[   0.   43.   67.    0.   38.]
 [ 100.   86.   96.  100.   94.]
 [  76.   79.   83.   89.   56.]
 [  88.   NaN   67.   89.   81.]
 [  94.   79.   67.   89.   69.]
 [  88.   79.   58.   72.   63.]
 [  76.   79.   71.   67.   56.]
 [  71.   71.   NaN   56.  100.]]

Ich versuche, jede Zeile einzeln zu nehmen, sie in umgekehrter Reihenfolge zu sortieren, um maximal 3 Werte aus der Zeile zu erhalten und ihren Durchschnitt zu ermitteln. Der Code, den ich ausprobiert habe, ist:

# nparr is a 2D numpy array
for entry in nparr:
    sortedentry = sorted(entry, reverse=True)
    highest_3_values = sortedentry[:3]
    avg_highest_3 = float(sum(highest_3_values)) / 3

Dies funktioniert nicht für Zeilen mit NaN. Meine Frage ist, gibt es eine schnelle Möglichkeit, alle NaNWerte im 2D-Numpy-Array in Null umzuwandeln, damit ich keine Probleme mit dem Sortieren und anderen Dingen habe, die ich versuche zu tun.


1
each: map: return isNaN(value) ? 0 : value
Kirilloid

@ Kirilloid: Hört sich gut an, wie wäre es mit Beispielnutzung?
serv-inc

Antworten:


114

Das sollte funktionieren:

from numpy import *

a = array([[1, 2, 3], [0, 3, NaN]])
where_are_NaNs = isnan(a)
a[where_are_NaNs] = 0

Im obigen Fall ist where_are_NaNs:

In [12]: where_are_NaNs
Out[12]: 
array([[False, False, False],
       [False, False,  True]], dtype=bool)

129

Wo Aist Ihr 2D-Array:

import numpy as np
A[np.isnan(A)] = 0

Die Funktion isnanerzeugt ein Bool-Array, das angibt, wo sich die NaNWerte befinden. Ein boolesches Array kann verwendet werden, um ein Array derselben Form zu indizieren. Stellen Sie es sich wie eine Maske vor.


37

Wie wäre es mit nan_to_num () ?


11
nan_to_num () ändert auch Unendlichkeiten - dies kann in einigen Fällen unerwünscht sein.
Agos

9
Es ist auch> 10x langsamer als die anderen Methoden.
Benutzer48956

7
Ich war mir nicht sicher über die Anweisung "> 10x langsam", also habe ich nachgesehen. In der Tat ist es so viel langsamer. Vielen Dank für den Hinweis.
Gabriel

12

Sie könnten verwenden, np.whereum herauszufinden, wo Sie haben NaN:

import numpy as np

a = np.array([[   0,   43,   67,    0,   38],
              [ 100,   86,   96,  100,   94],
              [  76,   79,   83,   89,   56],
              [  88,   np.nan,   67,   89,   81],
              [  94,   79,   67,   89,   69],
              [  88,   79,   58,   72,   63],
              [  76,   79,   71,   67,   56],
              [  71,   71,   np.nan,   56,  100]])

b = np.where(np.isnan(a), 0, a)

In [20]: b
Out[20]: 
array([[   0.,   43.,   67.,    0.,   38.],
       [ 100.,   86.,   96.,  100.,   94.],
       [  76.,   79.,   83.,   89.,   56.],
       [  88.,    0.,   67.,   89.,   81.],
       [  94.,   79.,   67.,   89.,   69.],
       [  88.,   79.,   58.,   72.,   63.],
       [  76.,   79.,   71.,   67.,   56.],
       [  71.,   71.,    0.,   56.,  100.]])

1
wie es ist, es nicht funktioniert, müssen Sie ändern np.where(np.isnan(a), a, 0)zu np.where(~np.isnan(a), a, 0). Dies kann jedoch ein Unterschied in den verwendeten Versionen sein.
TehTris

1
@TehTris du hast recht, danke. Ich habe es geändert, b = np.where(np.isnan(a), 0, a)was einfacher ist ~als mit, wie ich denke.
Anton Protopopov

10

Ein Codebeispiel für Drakes Antwort auf den Einsatz nan_to_num:

>>> import numpy as np
>>> A = np.array([[1, 2, 3], [0, 3, np.NaN]])
>>> A = np.nan_to_num(A)
>>> A
array([[ 1.,  2.,  3.],
       [ 0.,  3.,  0.]])

3

Sie können numpy.nan_to_num verwenden :

numpy.nan_to_num (x): Ersetzen Sie nan durch Null und inf durch endliche Zahlen .

Beispiel (siehe Dokument):

>>> np.set_printoptions(precision=8)
>>> 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])

1

nan ist niemals gleich nan

if z!=z:z=0

also für ein 2D-Array

for entry in nparr:
    if entry!=entry:entry=0

Dies funktioniert nicht: entryist ein 1D-Array, daher gibt der Test entry != entrykeinen einfachen Booleschen Wert aus, sondern erhöht ValueError.
Eric O Lebigot

-1

Sie können die Lambda-Funktion verwenden, ein Beispiel für ein 1D-Array:

import numpy as np
a = [np.nan, 2, 3]
map(lambda v:0 if np.isnan(v) == True else v, a)

Dies gibt Ihnen das Ergebnis:

[0, 2, 3]

-7

Wenn für Ihre Zwecke alle Elemente als gespeichert sind strund Sie nur sortiert verwenden, während Sie verwenden, suchen Sie nach dem ersten Element und ersetzen Sie es durch '0'.

>>> l1 = ['88','NaN','67','89','81']
>>> n = sorted(l1,reverse=True)
['NaN', '89', '88', '81', '67']
>>> import math
>>> if math.isnan(float(n[0])):
...     n[0] = '0'
... 
>>> n
['0', '89', '88', '81', '67']

6
Ist dein Kommentar nicht etwas hart? Ich weiß, was Numpy ist, wusste aber, dass das Array keine Zeichenfolgendarstellung von Zahlen ist. Ich habe dies speziell nicht aus der Perspektive der Numpy, sondern aus der Perspektive von Python betrachtet, wenn das nützlich war.
Senthil Kumaran

1
Das Neuanordnen des Arrays klingt nach einer verwirrenden Lösung.
Holografix
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.