Inicialización de matriz NumPy (rellenar con valores idénticos) [duplicado]

Resuelto max asked hace 13 años • 9 respuestas

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é zerosy onesfuncionaría para v = 0, 1. Podría usarlo v * ones(n), pero no funcionará cuando vsea Noney también sería mucho más lento.

max avatar May 05 '11 07:05 max
Aceptado

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

Eric O. Lebigot avatar Dec 16 '2013 08:12 Eric O. Lebigot

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
Yariv avatar Oct 24 '2012 15:10 Yariv

Creo fillque 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[:] = vlogrará lo que hace su iteración usando numpy broadcasting .

Paul avatar May 05 '2011 00:05 Paul

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

ingrese la descripción de la imagen aquí

Las dos emptyalternativas siguen siendo las más rápidas (con NumPy 1.12.1). fullse 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,
)
Nico Schlömer avatar Jul 05 '2017 08:07 Nico Schlömer

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.

Rolf Bartstra avatar Nov 05 '2012 13:11 Rolf Bartstra