Я произвожу список размерных множеств numpy в петле и позже преобразовываю этот список в 2-е множество numpy. Я предварительно ассигновал бы 2-е множество numpy, если я знал количество пунктов заранее, но я не делаю, поэтому я поместил все в список.
Насмешка - ниже:
>>> list_of_arrays = map(lambda x: x*ones(2), range(5))
>>> list_of_arrays
[array([ 0., 0.]), array([ 1., 1.]), array([ 2., 2.]), array([ 3., 3.]), array([ 4., 4.])]
>>> arr = array(list_of_arrays)
>>> arr
array([[ 0., 0.],
[ 1., 1.],
[ 2., 2.],
[ 3., 3.],
[ 4., 4.]])
Мой вопрос следующий:
Есть ли лучший путь (performancewise), чтобы пойти о задаче сбора последовательных числовых данных (в моем случае numpy множества), чем помещение их в списке и затем создании numpy.array из него (я создаю новый obj и копирую данные)? Есть ли «растяжимая» матричная структура данных, доступная в хорошо проверенном модуле?
Типичный размер моей 2-й матрицы был бы между 100x10 и 5000x10 плавания
Править: В этом примере я использую карту, но в моем фактическом заявлении я имею для петли
Вы знаете, что окончательный массив ARR
никогда не будет больше 5000х10.
Тогда вы можете предварительно выделить массив максимального размера, заполнить его с данными как
Вы проходите через петлю, а затем используете ARR.Resize
, чтобы сократить его до
Обнаруженный размер после выхода цикла.
Тесты ниже предполагают, что будет немного быстрее, чем построение промежуточных Списки Python Независимо от того, какой максимальный размер массива.
также ARR.RESIZE
de-выделенные неиспользованные память, поэтому финал (хотя, возможно, не промежуточный) след памяти меньше, чем используется Python_Lists_to_Array
.
Это показывает numpy_all_the_way
быстрее:
% python -mtimeit -s"import test" "test.numpy_all_the_way(100)"
100 loops, best of 3: 1.78 msec per loop
% python -mtimeit -s"import test" "test.numpy_all_the_way(1000)"
100 loops, best of 3: 18.1 msec per loop
% python -mtimeit -s"import test" "test.numpy_all_the_way(5000)"
10 loops, best of 3: 90.4 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(100)"
1000 loops, best of 3: 1.97 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(1000)"
10 loops, best of 3: 20.3 msec per loop
% python -mtimeit -s"import test" "test.python_lists_to_array(5000)"
10 loops, best of 3: 101 msec per loop
Это показывает numpy_all_the_way
использует меньше памяти:
% test.py
Initial memory usage: 19788
After python_lists_to_array: 20976
After numpy_all_the_way: 20348
test.py:
import numpy as np
import os
def memory_usage():
pid = os.getpid()
return next(line for line in open('/proc/%s/status' % pid).read().splitlines()
if line.startswith('VmSize')).split()[-2]
N, M = 5000, 10
def python_lists_to_array(k):
list_of_arrays = list(map(lambda x: x * np.ones(M), range(k)))
arr = np.array(list_of_arrays)
return arr
def numpy_all_the_way(k):
arr = np.empty((N, M))
for x in range(k):
arr[x] = x * np.ones(M)
arr.resize((k, M))
return arr
if __name__ == '__main__':
print('Initial memory usage: %s' % memory_usage())
arr = python_lists_to_array(5000)
print('After python_lists_to_array: %s' % memory_usage())
arr = numpy_all_the_way(5000)
print('After numpy_all_the_way: %s' % memory_usage())
Я добавлю свою собственную версию ответа ЮНУТБУ. Похоже на numpy_all_the., Но вы динамически разместитесь, если у вас есть ошибка индекса. Я думал, что это было бы немного быстрее для небольших наборов данных, но это немного медленнее - границы проверки замедливают вещи слишком много.
initial_guess = 1000
def my_numpy_all_the_way(k):
arr=np.empty((initial_guess,M))
for x,row in enumerate(make_test_data(k)):
try:
arr[x]=row
except IndexError:
arr.resize((arr.shape[0]*2, arr.shape[1]))
arr[x]=row
arr.resize((k,M))
return arr
Что вы делаете, это стандартный путь. Свойство Numpy массивов в том, что им нужна смежная память. Единственная возможность «отверстий», которые я могу думать, что может подумать, возможно с помощью шагов
PyarrayObject
, но это не влияет на обсуждение здесь. Поскольку многие массивы имеют смежные память и «Prallocated», добавляя новую строку / столбец означает выделение новой памяти, копирования данных, а затем освобождая старую память. Если вы сделаете это много, это не очень эффективно.
Один случай, когда кто-то может не захотеть создавать список, а затем преобразовать его в небольшой массив в конце, когда список содержит много номеров: Numpy roadious чисел занимает гораздо меньшее пространство, чем нативный список Python Числа (поскольку нативный список Python хранит объекты Python). Для ваших типичных размеров массива я не думаю, что это проблема.
Когда вы создаете свой окончательный массив из списка массивов, вы копирование всех данных в новое место для нового (2-D в вашем примере) массива. Это все еще намного эффективнее, чем наличие Numpy Array и делать Next = numpy.vstack ((next, new_row))
каждый раз, когда вы получаете новые данные. VStack ()
будет скопировать все данные для каждой «строки».
Был поток на списке Numpy-Desmention Meeting , который обсудил возможность добавления нового типа массива Numpy, который позволяет эффективно расширить / добавить. Похоже, что в то время был значительный интерес к этому времени, хотя я не знаю, произошло ли что-то из этого. Возможно, вы захотите посмотреть на эту тему.
Я бы сказал, что то, что вы делаете, - это очень питон, и эффективно, поэтому, если вам действительно не нужно что-то еще (больше космической эффективности, может быть?), Вы должны быть в порядке. Вот как я создаю свои Numpy Armays, когда я не знаю количество элементов в массиве в начале.