Necesito cambiar todos los nans de una matriz a un valor diferente. Puedo obtener fácilmente las posiciones nan usando argwhere, pero no estoy seguro de cómo acceder a esas posiciones mediante programación. Aquí está mi código que no funciona:

myMatrix = np.array([[3.2,2,float('NaN'),3],[3,1,2,float('NaN')],[3,3,3,3]])

nanPositions = np.argwhere(np.isnan(myMatrix))
maxVal = np.nanmax(abs(myMatrix))
for pos in nanPositions :
    myMatrix[pos] = maxval

El problema es que myMatrix [pos] no acepta pos como una matriz.

0
andy 14 sep. 2018 a las 18:19

3 respuestas

La mejor respuesta
In [54]: arr = np.array([[3.2,2,float('NaN'),3],[3,1,2,float('NaN')],[3,3,3,3]])
    ...: 
In [55]: arr
Out[55]: 
array([[3.2, 2. , nan, 3. ],
       [3. , 1. , 2. , nan],
       [3. , 3. , 3. , 3. ]])

Ubicación de la nan:

In [56]: np.where(np.isnan(arr))
Out[56]: (array([0, 1]), array([2, 3]))
In [57]: np.argwhere(np.isnan(arr))
Out[57]: 
array([[0, 2],
       [1, 3]])

where produce una tupla de matrices; argwhere los mismos valores pero como una matriz 2d

In [58]: arr[Out[56]]
Out[58]: array([nan, nan])
In [59]: arr[Out[56]] = [100,200]
In [60]: arr
Out[60]: 
array([[  3.2,   2. , 100. ,   3. ],
       [  3. ,   1. ,   2. , 200. ],
       [  3. ,   3. ,   3. ,   3. ]])

El argwhere se puede usar para indexar elementos individuales:

In [72]: for ij in Out[57]:
    ...:     print(arr[tuple(ij)]) 
100.0
200.0

Aquí se necesita tuple() porque np.array([1,3]) se interpreta como indexación de 2 elementos en la primera dimensión.

Otra forma de obtener esa tupla de indexación es usar unpacking:

In [74]: [arr[i,j] for i,j in Out[57]]
Out[74]: [100.0, 200.0]

Entonces, aunque argparse parece útil, es más complicado de usar que el simple where.

Podría, como se señaló en las otras respuestas, utilizar la indexación booleana (ya he modificado arr para que la prueba isnan ya no funcione):

In [75]: arr[arr>10]
Out[75]: array([100., 200.])

Más sobre indexación con una lista o matriz e indexación con una tupla:

In [77]: arr[[0,0]]      # two copies of row 0
Out[77]: 
array([[  3.2,   2. , 100. ,   3. ],
       [  3.2,   2. , 100. ,   3. ]])
In [78]: arr[(0,0)]      # one element
Out[78]: 3.2

In [79]: arr[np.array([0,0])]         # same as list
Out[79]: 
array([[  3.2,   2. , 100. ,   3. ],
       [  3.2,   2. , 100. ,   3. ]])
In [80]: arr[np.array([0,0]),:]       # making the trailing : explicit
Out[80]: 
array([[  3.2,   2. , 100. ,   3. ],
       [  3.2,   2. , 100. ,   3. ]])
1
hpaulj 14 sep. 2018 a las 16:40

sacul ha cubierto la forma más eficiente de generar su salida. Sin embargo, está indexando incorrectamente su matriz 2D en el caso en que desea utilizar una matriz.

Al menos para mí, es un poco intuitivo, pero debes usar:

myMatrix[[all_row_indices], [all_column_indices]] 

Lo siguiente le dará lo que espera:

import numpy as np

myMatrix = np.array([[3.2,2,float('NaN'),3],[3,1,2,float('NaN')],[3,3,3,3]])

nanPositions = np.argwhere(np.isnan(myMatrix))
maxVal = np.nanmax(abs(myMatrix))

print(myMatrix[nanPositions[:, 0], nanPositions[:, 1]])

Puede ver más sobre la indexación avanzada en documentación

2
roganjosh 14 sep. 2018 a las 15:44

Puedes hacer esto en su lugar (IIUC):

myMatrix[np.isnan(myMatrix)] = np.nanmax(abs(myMatrix))
1
sacuL 14 sep. 2018 a las 15:22