Оптимальное решение зависит от чисел / размеров, с которыми вы имеете дело.
Мое любимое решение (которое работает только в том случае, если вы уже знаете размер конечного результата) - инициализировать массив, который будет содержать ваши результаты, а затем заполнить каждый, который вы можете инициализировать, а затем заполнить его, используя представления.
Это наиболее эффективное решение для памяти.
Если вы не знаете размер конечного результата, то вам лучше создать список списков, который можно преобразовать (или собрать в стек) в виде массива NumPy в конце процесса.
Вот несколько примеров, где gen_1d_list()
используется для генерации случайных чисел, имитирующих результат simulate3()
(это означает, что в следующем коде вы должны заменить gen_1d_list(n, dtype)
на simulate3()
):
stacking1()
реализует заполнение с использованием представлений
stacking2()
реализует генерацию списка и преобразовывает в массив NumPy
stacking3()
реализует генерацию списка и укладку в массив NumPy
stacking4()
реализует динамическое изменение массива NumPy с использованием vstack()
, как предлагалось ранее.
import numpy as np
def gen_1d_list(n, dtype=int):
return list(np.random.randint(1, 100, n, dtype))
def stacking1(n, m, dtype=int):
arr = np.empty((n, m), dtype=dtype)
for i in range(n):
arr[i] = gen_1d_list(m, dtype)
return arr
def stacking2(n, m, dtype=int):
items = [gen_1d_list(m, dtype) for i in range(n)]
arr = np.array(items)
return arr
def stacking3(n, m, dtype=int):
items = [gen_1d_list(m, dtype) for i in range(n)]
arr = np.stack(items, dtype)
return arr
def stacking4(n, m, dtype=int):
arr = np.zeros((0, m), dtype=dtype)
for i in range(n):
arr = np.vstack((gen_1d_list(m, dtype), arr))
return arr
По времени stacking1()
и stacking2()
более или менее одинаково быстро, в то время как stacking3()
и stacking4()
медленнее (и, пропорционально, намного медленнее для входов малого размера).
Некоторые цифры для небольших входных данных:
n, m = 4, 10
%timeit stacking1(n, m)
# 15.7 µs ± 182 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit stacking2(n, m)
# 14.2 µs ± 141 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit stacking3(n, m)
# 22.7 µs ± 282 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit stacking4(n, m)
# 31.8 µs ± 270 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
и для входов большего размера:
n, m = 4, 1000000
%timeit stacking1(n, m)
# 344 ms ± 1.64 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit stacking2(n, m)
# 350 ms ± 1.65 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit stacking3(n, m)
# 370 ms ± 2.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit stacking4(n, m)
# 369 ms ± 3.01 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)