Создание пустого массива NumPy и постепенное его заполнение

На данный момент программа постепенно записывает в пустой список большой объём данных. Делает примерно так:

import time

# Создаю пустые списки
z_gyro_row = []  
collect_time_row = []  
START_TIME = time.time()
  
# В цикле по определённому условию считываю данные с датчика
# И постепенно заполняю пустые списки
while flag:
            collect_time = time.time() - START_TIME  # Фиксируем отрезок времени
            collect_time_row.append(collect_time)  # Запись времени в список
            z_gyro_32 = gyro_out32(z_gyro_32)  # Считываю значение с датчика
            z_gyro_row.append(z_gyro_32)  # Запись значений в список

На один из моих вопросов, мне посоветовали для большого объёма данных использовать массивы NumPy. Сейчас я это попытался сделать, но как я понимаю их невозможно так же как и списки постепенно заполнять данными с помощью команды .append. Попытался так, но не вышло:

import numpy as np

my_array = np.array([], 'float64')
np.append(my_array, 10)

Возможно только преобразовать list в numpy.ndarray. В связи с этим возникает вопрос как оптимально использовать массивы NumPy, чтобы тратить как можно меньше времени и ресурсов на запись/хранение/обработку данных?


Ответы (3 шт):

Автор решения: Андрей Крузлик

Массив не изменяем

import numpy as np

my_array = np.array(['a', 'd'])
my_array2 =  np.append(my_array, 'w', )
print(my_array)
print(my_array2)

Использование np.append :

my_array  = np.array([0])
for i in range(int(10)):
    my_array = np.append(my_array , i)

Использование python преобразования списка в массив после этого:

my_list= [0]
for k in range(int(10)):
    my_array.append(k)
my_array = np.array(my_array )

Предварительное выделение массива numpy:

e = np.zeros((n,))
for k in range(n):
    e[k] = k
→ Ссылка
Автор решения: passant

Да, массивы - неизменяемый (не расширяемый) тип данных. Это цена за скорость работы. Вообще-то ничего нового и страшного: классические массивы в том-же С++ именно так и работают. Уже десятки лет. И еще столько-же будут использоваться и работать.

Теперь что делать. Самое худшее из возможных решений - работать с ними как со списками, т.е. порождать пустым, а потом добавлять по мере необходимости по одному элементу. Разумный путь - определить максимально возможное (в будущем) количество элементов в массиве, порождать массив именно такого размера, а потом заполнять его элементы по мере их появления. Промежуточный путь - породить массив большого (достаточного на первое время функционирования) размера, после исчерпания - добавлять новый фрагмент (опять - не на один элемент, конечно).

Поскольку у вас работа идет - мне так кажется - с датчиками, то у вас еще меньше проблем должно возникнуть, если конечно архитектуру приложения разработать нормально. В таких приложениях - нет необходимости хранить информацию бесконечно долго. Более того, есть такое понятие - окно наблюдения. По сути, сколько данных вы обрабатываете. И это окно как правило коненчо. Вот и создавайте массив соответствующего размера. Или два таких массива - один заполняется, данные из второго - обрабатываются. Кстати - заполнять можно действительно через список, который по только факту полного заполнения преобразуется в массив. Потом массивы меняются местами - второй наполняется, первый обрабатывается. Но архитектуру конечно надо при этом делать не спонтанно-интуитивно.

→ Ссылка
Автор решения: CrazyElf

Если данных не очень много (не миллионы значений), то вам вообще не имеет смысла мучиться с Numpy. Я потестил ради интереса, создал пустой список из добавил к нему по одному 1 000 000 (миллион) элементов. На это у питона ушло 100 миллисекунд.

Если такая скорость для вас мала, то тогда нужно выделять массив Numpy, например, с помощью np.empty заведомо большего размера, чем вам может понадобится, и заполнять его, обращаясь к элементам по индексу. Но это не так удобно, как работать со списком.

А ещё в питоне есть разные виды очередей, например, очень удобная collections.deque, которую можно читать и писать с обоих концов. Если вы то пишете в список, то читаете из него вперемешку, то использовать очередь ещё проще и удобнее, чем список. Опять же на примере миллиона элементов создание очереди путём добавления элементов с конца и с начала по очереди, а потом полное опустошение очереди опять же забиранием элементов с конца и с начала по очереди заняло чуть больше тех же 100 миллисекунд. Очень рекомендую очередь - весьма удобная коллекция.

→ Ссылка