Inicialización de matriz NumPy (rellenar con valores idénticos) [duplicado]
Necesito crear una matriz NumPy de longitud n
, cada elemento del cual sea v
.
¿Hay algo mejor que:
a = empty(n)
for i in range(n):
a[i] = v
Lo sé zeros
y ones
funcionaría para v = 0, 1. Podría usarlo v * ones(n)
, pero no funcionará cuando sería mucho más lento.v
sea None
y también
Se introdujo NumPy 1.8 np.full()
, que es un método más directo que empty()
el seguido por fill()
para crear una matriz llena con un determinado valor:
>>> np.full((3, 5), 7)
array([[ 7., 7., 7., 7., 7.],
[ 7., 7., 7., 7., 7.],
[ 7., 7., 7., 7., 7.]])
>>> np.full((3, 5), 7, dtype=int)
array([[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7],
[7, 7, 7, 7, 7]])
Podría decirse que esta es la forma de crear una matriz llena de ciertos valores, porque describe explícitamente lo que se está logrando (y, en principio, puede ser muy eficiente ya que realiza una tarea muy específica).
Actualizado para Numpy 1.7.0: (felicitación a @Rolf Bartstra).
a=np.empty(n); a.fill(5)
es más rápido.
En orden descendente de velocidad:
%timeit a=np.empty(10000); a.fill(5)
100000 loops, best of 3: 5.85 us per loop
%timeit a=np.empty(10000); a[:]=5
100000 loops, best of 3: 7.15 us per loop
%timeit a=np.ones(10000)*5
10000 loops, best of 3: 22.9 us per loop
%timeit a=np.repeat(5,(10000))
10000 loops, best of 3: 81.7 us per loop
%timeit a=np.tile(5,[10000])
10000 loops, best of 3: 82.9 us per loop
Creo fill
que es la forma más rápida de hacer esto.
a = np.empty(10)
a.fill(7)
También debes evitar siempre iterar como lo estás haciendo en tu ejemplo. Un simple a[:] = v
logrará lo que hace su iteración usando numpy broadcasting .
Lo tenía np.array(n * [value])
en mente, pero aparentemente es más lento que todas las demás sugerencias para tamaños suficientemente grandes n
. Lo mejor en términos de legibilidad y velocidad es
np.full(n, 3.14)
Aquí hay una comparación completa con perfplot (uno de mis proyectos favoritos).
Las dos empty
alternativas siguen siendo las más rápidas (con NumPy 1.12.1). full
se pone al día con arreglos grandes.
Código para generar la trama:
import numpy as np
import perfplot
def empty_fill(n):
a = np.empty(n)
a.fill(3.14)
return a
def empty_colon(n):
a = np.empty(n)
a[:] = 3.14
return a
def ones_times(n):
return 3.14 * np.ones(n)
def repeat(n):
return np.repeat(3.14, (n))
def tile(n):
return np.repeat(3.14, [n])
def full(n):
return np.full((n), 3.14)
def list_to_array(n):
return np.array(n * [3.14])
perfplot.show(
setup=lambda n: n,
kernels=[empty_fill, empty_colon, ones_times, repeat, tile, full, list_to_array],
n_range=[2 ** k for k in range(27)],
xlabel="len(a)",
logx=True,
logy=True,
)
Aparentemente, no sólo las velocidades absolutas sino también el orden de velocidad (según lo informado por el usuario1579844) dependen de la máquina; esto es lo que encontré:
a=np.empty(1e4); a.fill(5)
es más rápido;
En orden descendente de velocidad:
timeit a=np.empty(1e4); a.fill(5)
# 100000 loops, best of 3: 10.2 us per loop
timeit a=np.empty(1e4); a[:]=5
# 100000 loops, best of 3: 16.9 us per loop
timeit a=np.ones(1e4)*5
# 100000 loops, best of 3: 32.2 us per loop
timeit a=np.tile(5,[1e4])
# 10000 loops, best of 3: 90.9 us per loop
timeit a=np.repeat(5,(1e4))
# 10000 loops, best of 3: 98.3 us per loop
timeit a=np.array([5]*int(1e4))
# 1000 loops, best of 3: 1.69 ms per loop (slowest BY FAR!)
Así que intenta descubrirlo y utiliza lo que sea más rápido en tu plataforma.