Crear matriz numpy llena de NaN

6 minutos de lectura

avatar de usuario
elíseo devorado

Tengo el siguiente código:

r = numpy.zeros(shape = (width, height, 9))

Crea un width x height x 9 matriz llena de ceros. En cambio, me gustaría saber si hay una función o forma de inicializarlos en lugar de NaNs de una manera fácil.

  • Una advertencia es que NumPy no tiene un valor NA entero (a diferencia de R). Ver pandas lista de trampas. Por eso np.nan sale mal cuando se convierte a int.

    – smci

    28 de julio de 2013 a las 3:31


  • smci tiene razón. Para NumPy no existe tal valor de NaN. Entonces, depende del tipo y de NumPy qué valor estará allí para NaN. Si no es consciente de esto, le causará problemas.

    – Programa de control maestro

    4 de noviembre de 2016 a las 15:38

  • De hecho, parecería que hay margen para que una función np.nans imite np.zeros y np.ones, pero supongo que np.full es una generalización que excluye la necesidad de todas las funciones especializadas. Buena pregunta.

    – Adrián Tompkins

    21 de enero a las 11:25

avatar de usuario
u0b34a0f6ae

Rara vez necesita bucles para operaciones vectoriales en numpy. Puede crear una matriz no inicializada y asignarla a todas las entradas a la vez:

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

He cronometrado las alternativas a[:] = numpy.nan aquí y a.fill(numpy.nan) según lo publicado por Blaenk:

$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan" 
10000 loops, best of 3: 88.8 usec per loop

Los tiempos muestran una preferencia por ndarray.fill(..) como la alternativa más rápida. OTOH, me gusta la implementación conveniente de numpy donde puede asignar valores a segmentos completos en ese momento, la intención del código es muy clara.

Tenga en cuenta que ndarray.fill realiza su operación en el lugar, por lo que numpy.empty((3,3,)).fill(numpy.nan) en cambio, regresará None.

  • Estoy de acuerdo en que la intención de su código es más clara. Pero gracias por los tiempos imparciales (o más bien, el hecho de que todavía los publicaste), lo aprecio 🙂

    –Jorge Israel Peña

    10 de noviembre de 2009 a las 7:19

  • Me gusta este: a = numpy.empty((3, 3,)) * numpy.nan. Temporizó más rápido que fill pero más lento que el método de asignación, ¡pero es un oneliner!

    – Heltonbiker

    30 de abril de 2012 a las 14:09


  • Mire esta respuesta: stackoverflow.com/questions/10871220/…

    – Iván

    3 de junio de 2012 a las 15:15

  • Prefiero el .fill() método, pero la diferencia de velocidades se reduce a prácticamente nada a medida que las matrices se hacen más grandes.

    – nada101

    24 de marzo de 2014 a las 11:13

  • … porque np.empty([2, 5]) crea una matriz, entonces fill() modifica esa matriz en el lugar, pero no devuelve una copia o una referencia. si quieres llamar np.empty(2, 5) por un nombre (“asignar es a una variable”), debe hacerlo antes de realizar operaciones en el lugar. Lo mismo sucede si lo haces [1, 2, 3].insert(1, 4). Se crea la lista y se inserta un 4, pero es imposible obtener una referencia a la lista (y, por lo tanto, se puede suponer que se ha recolectado basura). En datos inmutables como cadenas, se devuelve una copia porque no puede operar en el lugar. Los pandas pueden hacer ambas cosas.

    – monstruo de la flauta7

    2 jun 2016 a las 21:26


avatar de usuario
pietro biroli

Otra opción es usar numpy.fulluna opción disponible en NumPy 1.8+

a = np.full([height, width, 9], np.nan)

Esto es bastante flexible y puede llenarlo con cualquier otro número que desee.

  • Yo consideraría esto como el más correcto respuesta ya que es exactamente lo que full está destinado a. np.empy((x,y))*np.nan es un buen subcampeón (y compatibilidad con versiones anteriores de numpy).

    – travc

    21/09/2015 a las 19:38

  • esto es mas lento que fill python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop

    – Farnabaz

    19 oct 2016 a las 13:29


  • @Farnabaz Si coloca el código equivalente dentro del ciclo de tiempo, son casi iguales. Los dos métodos son básicamente iguales, solo tiene el “np.empty” fuera del temporizador en el primero. python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop

    –Scott Staniewicz

    28 de octubre de 2018 a las 1:35


avatar de usuario
Nico Schlömer

Comparé las alternativas sugeridas para la velocidad y encontré que, para vectores/matrices suficientemente grandes para llenar, todas las alternativas excepto val * ones y array(n * [val]) son igualmente rápidos.

ingrese la descripción de la imagen aquí


Código para reproducir la trama:

import numpy
import perfplot

val = 42.0


def fill(n):
    a = numpy.empty(n)
    a.fill(val)
    return a


def colon(n):
    a = numpy.empty(n)
    a[:] = val
    return a


def full(n):
    return numpy.full(n, val)


def ones_times(n):
    return val * numpy.ones(n)


def list(n):
    return numpy.array(n * [val])


b = perfplot.bench(
    setup=lambda n: n,
    kernels=[fill, colon, full, ones_times, list],
    n_range=[2 ** k for k in range(20)],
    xlabel="len(a)",
)
b.save("out.png")

  • extraño que numpy.full(n, val) es más lento que a = numpy.empty(n) .. a.fill(val) ya que hace lo mismo internamente

    – endolito

    3 de agosto de 2019 a las 17:38

avatar de usuario
Jorge Israel Peña

Estás familiarizado con numpy.nan?

Puede crear su propio método como:

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a

Después

nans([3,4])

daría salida

array([[ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN]])

Encontré este código en un hilo de la lista de correo.

avatar de usuario
placas

Siempre puedes usar la multiplicación si no recuerdas inmediatamente el .empty o .full métodos:

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])

Por supuesto, también funciona con cualquier otro valor numérico:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])

Pero la respuesta aceptada de @ u0b34a0f6ae es 3 veces más rápida (ciclos de CPU, no ciclos cerebrales para recordar la sintaxis numpy;):

$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)[email protected]:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop

avatar de usuario
físico loco

Como se dijo, numpy.empty() es el camino a seguir. Sin embargo, para los objetos, fill() podría no hacer exactamente lo que crees que hace:

In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)

Una forma de evitarlo puede ser, por ejemplo:

In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)

avatar de usuario
JHBonarius

Otra posibilidad aún no mencionada aquí es usar el mosaico NumPy:

a = numpy.tile(numpy.nan, (3, 3))

también da

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

No sé acerca de la comparación de velocidad.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad