Pythonic способ создать множество numpy из списка множеств numpy

Я произвожу список размерных множеств 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 плавания

Править: В этом примере я использую карту, но в моем фактическом заявлении я имею для петли

40
задан Dragan Chupacabric 21 January 2010 в 01:21
поделиться

3 ответа

Вы знаете, что окончательный массив 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())
19
ответ дан 27 November 2019 в 01:46
поделиться

Я добавлю свою собственную версию ответа ЮНУТБУ. Похоже на 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
2
ответ дан 27 November 2019 в 01:46
поделиться

Что вы делаете, это стандартный путь. Свойство 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, когда я не знаю количество элементов в массиве в начале.

2
ответ дан 27 November 2019 в 01:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: