2011-05-05 20 views
129

necesito para crear una matriz NumPy de longitud n, cada elemento de los cuales es v.NumPy matriz de inicialización (llenar con valores idénticos)

¿Hay algo mejor que:

a = empty(n) 
for i in range(n): 
    a[i] = v 

zeros y ones trabajaría para v = 0, 1. Podría usar v * ones(n), pero no funcionará cuando v es None, y también serían ser mucho más lento.

+1

En mi equipo, para el caso 0, usando 'a = np.zeros (n)' en el bucle es más rápido que un '. llenar (0) '. Esto es contrario a lo que esperaba ya que pensé que 'a = np.zeros (n)' necesitaría asignar e inicializar la nueva memoria. Si alguien puede explicar esto, lo agradecería. – user3731622

Respuesta

148

NumPy 1,8 introducido np.full(), que es un método más directo que empty() seguido de fill() para la creación de una matriz llena de un cierto 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]]) 

Esto es posiblemente la forma de creación de 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).

+1

Este método full() funciona bien para mí, pero no puedo encontrar un poco de documentación para él. ¿Alguien puede indicarme el lugar correcto? –

+0

Al menos puedes hacer 'help (numpy.full)' en un shell de Python. También me sorprende que no esté en la documentación web. – EOL

+0

En mi sistema (Python 2.7, Numpy 1.8), np.full() es en realidad un poco más lento que np.empty() seguido de np.fill(). –

54

Creo fill es la forma más rápida de hacerlo.

a = np.empty(10) 
a.fill(7) 

Siempre debe evitar iterar como lo hace en su ejemplo. Un simple a[:] = v logrará lo que su iteración hace usando numpy broadcasting.

+1

Gracias. Al mirar 'fill', vi que' repeat' se adapta mejor a mis necesidades. – max

+0

¿Te importaría actualizar tu respuesta para decir que tu recomendación de 'a [:] = v' es realmente más rápida en general que el' fill'? – max

+0

@max ¿Es más rápido? La difusión es una forma más general de llenar una matriz y supongo que es más lenta o igual que el caso de uso muy estrecho de 'fill'. – Paul

5

Puede utilizar numpy.tile, por ejemplo, :

v = 7 
rows = 3 
cols = 5 
a = numpy.tile(v, (rows,cols)) 
a 
Out[1]: 
array([[7, 7, 7, 7, 7], 
     [7, 7, 7, 7, 7], 
     [7, 7, 7, 7, 7]]) 

Aunque tile está destinado a 'baldosas' una matriz (en lugar de un escalar, como en este caso), que va a hacer el trabajo, la creación de matrices precargadas de cualquier tamaño y dimensión.

76

Actualizado para la Numpy 1.7.0: (sombrero de punta a @Rolf Bartstra.)

a=np.empty(n); a.fill(5) es más rápido.

Para velocidad descendente:

%timeit a=np.empty(1e4); a.fill(5) 
100000 loops, best of 3: 5.85 us per loop 

%timeit a=np.empty(1e4); a[:]=5 
100000 loops, best of 3: 7.15 us per loop 

%timeit a=np.ones(1e4)*5 
10000 loops, best of 3: 22.9 us per loop 

%timeit a=np.repeat(5,(1e4)) 
10000 loops, best of 3: 81.7 us per loop 

%timeit a=np.tile(5,[1e4]) 
10000 loops, best of 3: 82.9 us per loop 
+10

Agregar un tiempo para el 'np.full()' más reciente y directo sería útil. En mi máquina, con NumPy 1.8.1, es aproximadamente un 15% más lenta que la versión menos directa 'fill()' (que es inesperada, ya que 'full()' tiene el potencial de ir un poco más rápido). – EOL

+0

@DavidSanders: No estoy seguro de que te sigo: 'fill()' es la solución más rápida. La solución de multiplicación es mucho más lenta. – EOL

+2

Nota: si la velocidad es realmente una preocupación, usar un tamaño de '10000' en lugar de' 1e4' hace una diferencia notable, por alguna razón ('lleno()' es casi un 50% más lento, con '1e4'). – EOL

13

Aparentemente, no sólo las velocidades absolutas, sino también a la orden de velocidad (según lo informado por user1579844) son dependiente de la máquina; esto es lo que encontré:

a=np.empty(1e4); a.fill(5) es más rápido;

Con el fin de velocidad descendente:

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!) 

Por lo tanto, tratar de averiguar, y utilizar lo que es más rápido en su plataforma.

6

tuve

numpy.array(n * [value]) 

en mente, pero al parecer es más lento que el resto de sugerencias para lo suficientemente grande n.

Aquí está la comparación completa con perfplot (un proyecto de mascota mío).

enter image description here

Las dos alternativas son empty siendo el más rápido (con NumPy 1.12.1). full alcanza 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(23)], 
    xlabel='len(a)', 
    logx=True, 
    logy=True, 
    ) 
Cuestiones relacionadas