Инициализация массива NumPy (заполнение с идентичными значениями)

Мне нужно создать массив NumPy длины n , каждый элемент которого равен v .

Есть ли что-то лучше, чем:

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

Я знаю, что zeros и ones будут работать для v = 0, 1. Я мог бы использовать v * ones(n) , но он не будет работать, если vNone , а также будет намного медленнее.

В NumPy 1.8 введен np.full() , который является более прямым методом, чем empty() за которым следует fill() для создания массива, заполненного определенным значением:

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

Это, возможно, способ создания массива, заполненного определенными значениями, поскольку он явно описывает то, что достигается (и это может в принципе быть очень эффективным, поскольку оно выполняет очень специфическую задачу).

Обновлено для Numpy 1.7.0: (Hat-tip для @ Rolf Bartstra.)

a=np.empty(n); a.fill(5) a=np.empty(n); a.fill(5) является самым быстрым.

В порядке убывания скорости:

 %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 

Я считаю, что fill – это самый быстрый способ сделать это.

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

Вы также должны всегда избегать повторения, как в своем примере. Простой параметр a[:] = v выполнит то, что делает ваша итерация, используя широковещательную передачу numpy.

По-видимому, не только абсолютные скорости, но и скорость (как указано пользователем1579844) зависят от машины; вот что я нашел:

a=np.empty(1e4); a.fill(5) a=np.empty(1e4); a.fill(5) является самым быстрым;

В порядке убывания скорости:

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

Итак, попробуйте и узнайте, и используйте то, что быстрее на вашей платформе.

Вы можете использовать numpy.tile , например:

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

Хотя tile предназначена для «разбиения» массива (вместо скаляра, как в этом случае), он выполнит задание, создав предварительно заполненные массивы любого размера и размера.

я имел

 numpy.array(n * [value]) 

но, по-видимому, это медленнее, чем все другие предложения для достаточно больших n .

Вот полное сравнение с perfplot ( мой любимый проект).

введите описание изображения здесь

Две empty альтернативы по-прежнему самые быстрые (с NumPy 1.12.1). full улавливает большие массивы.


Код для генерации сюжета:

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