Crea una width x height x 9matriz llena de ceros. En cambio, me gustaría saber si hay una función o forma de inicializarlos en lugar de hacerlo NaNde una manera fácil.
Una advertencia es que NumPy no tiene un valor de NA entero (a diferencia de R). Ver la lista de pandas de las trampas . Por lo tanto, np.nansale mal cuando se convierte a int.
smci
smci tiene razón. Para NumPy no existe dicho valor de NaN. Por lo tanto, depende del tipo y de NumPy qué valor estará allí para NaN. Si no está al tanto de esto, causará problemas
MasterControlProgram
Respuestas:
271
Raramente 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.nanaquí 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 ndarray.fill(..)como la alternativa más rápida. OTOH, me gusta la implementación de conveniencia de numpy donde puede asignar valores a segmentos enteros en ese momento, la intención del código es muy clara.
Tenga en cuenta que ndarray.fillrealiza su operación en el lugar, por numpy.empty((3,3,)).fill(numpy.nan)lo que en su lugar regresará None.
Estoy de acuerdo en que la intención de su código es más clara. Pero gracias por los horarios imparciales (o más bien, el hecho de que todavía los publicaste), lo aprecio :)
Jorge Israel Peña
2
Yo como éste: a = numpy.empty((3, 3,)) * numpy.nan. ¡Se cronometró más rápido fillpero más lento que el método de asignación, pero es una línea!
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.
naught101
44
... porque np.empty([2, 5])crea una matriz, luego fill()modifica esa matriz en el lugar, pero no devuelve una copia o una referencia. Si desea llamar np.empty(2, 5)por un nombre ("asignar es a una variable"), debe hacerlo antes de realizar operaciones in situ en él. Lo mismo pasa 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.
flutefreak7
164
Otra opción es usar numpy.full, una 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.
Consideraría esto como la respuesta más correcta, ya que es exactamente para lo que fullestá destinado. np.empy((x,y))*np.nanes un buen finalista (y compatibilidad para versiones antiguas de numpy).
travc
esto es más lento quefillpython -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
55
@Farnabaz Si coloca el código equivalente dentro del ciclo de sincronización, son casi iguales. Los dos métodos son básicamente iguales, acaba de obtener 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
48
Comparé las alternativas sugeridas para la velocidad y descubrí que, para vectores / matrices lo suficientemente grandes como para llenar, todas las alternativas excepto val * onesy array(n * [val])son igualmente rápidas.
Código para reproducir la trama:
import numpy
import perfplot
val =42.0def 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])
perfplot.show(
setup=lambda n: n,
kernels=[fill, colon, full, ones_times, list],
n_range=[2** k for k in range(20)],
logx=True,
logy=True,
xlabel="len(a)",)
@MadPhysicist Eso depende completamente de tu situación. Si tiene que inicializar solo una única matriz NaN, entonces sí, una función personalizada probablemente sea exagerada. Sin embargo, si tiene que inicializar una matriz NaN en docenas de lugares en su código, entonces tener esta función se vuelve bastante conveniente.
Xukrao
1
@Xukaro. En realidad no, dado que ya existe una versión más flexible y eficiente de dicha función y se menciona en muchas otras respuestas.
Físico loco
10
Siempre puede usar la multiplicación si no recuerda inmediatamente los métodos .emptyo .full:
Pero el @ u0b34a0f6ae's respuesta aceptada de es 3 veces más rápida (ciclos de CPU, no ciclos cerebrales para recordar 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)laneh@predict:~/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
Otra alternativa es numpy.broadcast_to(val,n) que regresa en tiempo constante sin importar el tamaño y también es la memoria más eficiente (devuelve una vista del elemento repetido). La advertencia es que el valor devuelto es de solo lectura.
A continuación se muestra una comparación de las actuaciones de todos los otros métodos que se han propuesto utilizando el mismo punto de referencia que en la respuesta de Nico Schlömer .
Como se dijo, numpy.empty () es el camino a seguir. Sin embargo, para los objetos, fill () podría no hacer exactamente lo que cree 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)
Aparte de no tener prácticamente nada que ver con la pregunta original, ordenada.
Mad Physicist
1
Bueno, se trata de "Inicializar matriz numpy en algo diferente a cero o uno", en el caso de "algo más" es un objeto :) (Más prácticamente, google me llevó aquí para inicializar con una lista vacía)
ntg
3
Otra posibilidad aún no mencionada aquí es usar el mosaico NumPy:
np.nan
sale mal cuando se convierte a int.Respuestas:
Raramente necesita bucles para operaciones vectoriales en numpy. Puede crear una matriz no inicializada y asignarla a todas las entradas a la vez:
He cronometrado las alternativas
a[:] = numpy.nan
aquí ya.fill(numpy.nan)
según lo publicado por Blaenk:Los tiempos muestran una preferencia
ndarray.fill(..)
como la alternativa más rápida. OTOH, me gusta la implementación de conveniencia de numpy donde puede asignar valores a segmentos enteros 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, pornumpy.empty((3,3,)).fill(numpy.nan)
lo que en su lugar regresaráNone
.fuente
a = numpy.empty((3, 3,)) * numpy.nan
. ¡Se cronometró más rápidofill
pero más lento que el método de asignación, pero es una línea!.fill()
método, pero la diferencia de velocidades se reduce a prácticamente nada a medida que las matrices se hacen más grandes.np.empty([2, 5])
crea una matriz, luegofill()
modifica esa matriz en el lugar, pero no devuelve una copia o una referencia. Si desea llamarnp.empty(2, 5)
por un nombre ("asignar es a una variable"), debe hacerlo antes de realizar operaciones in situ en él. Lo mismo pasa 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.Otra opción es usar
numpy.full
, una opción disponible en NumPy 1.8+Esto es bastante flexible y puede llenarlo con cualquier otro número que desee.
fuente
full
está destinado.np.empy((x,y))*np.nan
es un buen finalista (y compatibilidad para versiones antiguas de numpy).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
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
Comparé las alternativas sugeridas para la velocidad y descubrí que, para vectores / matrices lo suficientemente grandes como para llenar, todas las alternativas excepto
val * ones
yarray(n * [val])
son igualmente rápidas.Código para reproducir la trama:
fuente
numpy.full(n, val)
sea más lento quea = numpy.empty(n) .. a.fill(val)
porque hace lo mismo internamente¿Estás familiarizado con
numpy.nan
?Puede crear su propio método, como:
Luego
saldría
Encontré este código en un hilo de la lista de correo .
fuente
Siempre puede usar la multiplicación si no recuerda inmediatamente los métodos
.empty
o.full
:Por supuesto, también funciona con cualquier otro valor numérico:
Pero el @ u0b34a0f6ae's respuesta aceptada de es 3 veces más rápida (ciclos de CPU, no ciclos cerebrales para recordar sintaxis numpy;):
fuente
Otra alternativa es
numpy.broadcast_to(val,n)
que regresa en tiempo constante sin importar el tamaño y también es la memoria más eficiente (devuelve una vista del elemento repetido). La advertencia es que el valor devuelto es de solo lectura.A continuación se muestra una comparación de las actuaciones de todos los otros métodos que se han propuesto utilizando el mismo punto de referencia que en la respuesta de Nico Schlömer .
fuente
Como se dijo, numpy.empty () es el camino a seguir. Sin embargo, para los objetos, fill () podría no hacer exactamente lo que cree que hace:
Una forma de evitarlo puede ser, por ejemplo:
fuente
Otra posibilidad aún no mencionada aquí es usar el mosaico NumPy:
También da
No sé sobre la comparación de velocidad.
fuente