Инициализация массива NumPy (заполнение с идентичными значениями)
Мне нужно создать массив NumPy длиной n
, каждый элемент которого равен v
.
Есть ли что-нибудь лучше, чем:
a = empty(n)
for i in range(n):
a[i] = v
Я знаю, что zeros
и ones
будут работать для v = 0, 1. Я мог бы использовать v * ones(n)
, но он не будет работать, когда v
равно None
, а также будет намного медленнее.
Ответы
Ответ 1
В 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]])
Это, возможно, способ создания массива, заполненного определенными значениями, поскольку он явно описывает достигнутое (и в принципе может быть очень эффективным, поскольку он выполняет очень специфическую задачу).
Ответ 2
Обновлено для Numpy 1.7.0: (Hat-tip для @Rolf Bartstra.)
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
Ответ 3
Я считаю, fill
- самый быстрый способ сделать это.
a = np.empty(10)
a.fill(7)
Вы также должны всегда избегать повторения, как в своем примере. Простой a[:] = v
выполнит то, что делает ваша итерация, используя numpy broadcasting.
Ответ 4
По-видимому, не только абсолютные скорости, но и скорость (как указано пользователем1579844) зависят от машины; вот что я нашел:
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!)
Итак, попробуйте и узнайте, и используйте то, что быстрее всего на вашей платформе.
Ответ 5
я имел
numpy.array(n * [value])
в виду, но, видимо, это медленнее, чем все другие предложения для достаточно большого n
.
Вот полное сравнение с перфплотом (мой любимый проект).
![enter image description here]()
Две 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(27)],
xlabel='len(a)',
logx=True,
logy=True,
)
Ответ 6
Вы можете использовать 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
предназначен для "разбиения" массива (вместо скаляра, как в этом случае), он выполнит задание, создав предварительно заполненные массивы любого размера и размера.
Ответ 7
без обалденных
>>>[2]*3
[2, 2, 2]