python - transpuesta - Inicializando la matriz numpy a algo que no sea cero o uno
que es un array en python (7)
Tengo el siguiente código:
r = numpy.zeros(shape = (width, height, 9))
Crea una matriz de ancho x alto x 9 llena de ceros. En cambio, me gustaría saber si hay una función o una forma de inicializarlos en vez de NaN.
¿Hay alguna? Sin tener que recurrir a hacer bucles de forma manual y tal?
Gracias
¿Estás familiarizado con numpy.nan
?
Puedes crear tu propio método como:
def nans(shape, dtype=float):
a = numpy.empty(shape, dtype)
a.fill(numpy.nan)
return a
Entonces
nans([3,4])
saldría
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 .
Como se dijo, numpy.empty () es el camino a seguir. Sin embargo, para 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)
Comparé las alternativas sugeridas para la velocidad y descubrí que, para vectores / matrices suficientemente grandes como para llenar, todas las alternativas, excepto val * ones
y array(n * [val])
son igualmente rápidas.
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])
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)''
)
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 completarlo con cualquier otro número que desee.
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é sobre la comparación de velocidad.
Raramente necesitas 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)
tal como las publicó 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 de conveniencia de Numpy, donde puedes asignar valores a rebanadas enteras en el momento, la intención del código es muy clara.
Siempre puede usar la multiplicación si no recuerda inmediatamente los métodos .empty
o .full
:
>>> 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)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