python loadtxt из многих файлов, добавление в одни и те же массивы numpy

Я новичок в python и хочу наиболее питонический способ решения следующей основной проблемы:

У меня есть много файлов данных с открытым текстом file.00001, file.00002,..., file.99999, и каждый файл имеет одну строку с числовыми данными, хранящимися, например. четыре колонки. Я хочу читать каждый файл последовательно и добавлять данные в один массив для каждого столбца, поэтому в конце концов мне нужны массивы arr0, arr1, arr2, arr3, каждый из которых shape=(99999,) содержит все данные из соответствующего столбца во всех файлах.

Позже я хочу проделать много математических операций с этими массивами, поэтому мне нужно убедиться, что их записи непрерывны в памяти. Мое наивное решение:

import numpy as np
fnumber = 99999
fnums = np.arange(1, fnumber+1)

arr0 = np.full_like(fnums, np.nan, dtype=np.double)
arr1 = np.full_like(fnums, np.nan, dtype=np.double)
arr2 = np.full_like(fnums, np.nan, dtype=np.double)
arr3 = np.full_like(fnums, np.nan, dtype=np.double)
# ...also is there a neat way of doing this??

for fnum in fnums:
    fname = f'path/to/data/folder/file.{fnum:05}'
    arr0[fnum-1], arr1[fnum-1], arr2[fnum-1], arr3[fnum-1] = np.loadtxt(fname, delimiter=' ', unpack=True)

# error checking - in case a file got deleted or something
all_arrs = (arr0, arr1, arr2, arr3)
if np.isnan(all_arrs).any():
    print("CUIDADO HAY NANS!!!!\nLOOK OUT, THERE ARE NANS!!!!")

Меня поражает, что это очень C-мышление, и, вероятно, есть более питонический способ сделать это. Но мне кажется, что такие методы, как numpy.concatenate и numpy.insert, либо не приведут к созданию массивов с непрерывным содержимым в памяти, либо задействуют глубокие копии каждого массива на каждом этапе цикла for, что, вероятно, расплавит мой ноутбук.

Есть ли более питонический способ?


person jms547    schedule 04.11.2020    source источник
comment
all_arrs — это кортеж массивов. np.isnan превратит это в один массив (например, np.array(all_arrs), вернув логический массив формы (4,100000?).   -  person hpaulj    schedule 05.11.2020


Ответы (1)


Пытаться:

alist = []
for fnum in fnums:
    fname = f'path/to/data/folder/file.{fnum:05}'
    alist.append(np.loadtxt(fname))
arr = np.array(alist)
# arr = np.vstack(alist)    # alternative
print(arr.shape)

Предполагая, что все файлы имеют одинаковое количество столбцов, один из них должен работать. Результатом будет один массив, который при необходимости можно разделить на 4.

person hpaulj    schedule 04.11.2020
comment
Как это работает? Внутри цикла for вы добавляете alist, а затем снаружи переделываете (??) alist как ndarray, который заботится об эффективном распределении памяти? Кажется, все в порядке, за исключением того, что массивы numpy являются строковыми и не являются непрерывными элементами в столбце на расстоянии 4 адреса памяти друг от друга, а не рядом друг с другом? (Кроме того, ваш метод сохраняет одни и те же данные дважды, один раз в alist и один раз в arr, но я думаю, что это не проблема с несколькими тысячами чисел. - person jms547; 05.11.2020
comment
loadtxt загружает файл построчно и строит результат из полученного списка списков. На самом деле не имеет значения, собираете ли вы список массивов и создаете из них массив или назначаете эти массивы фрагментам предопределенного массива. Использование памяти и копирование в основном одинаковы. Помните, что список содержит ссылки/указатели на объекты в другом месте в памяти. - person hpaulj; 05.11.2020
comment
appending массивов в список весьма эффективен, так как он просто добавляет ссылку на список. Выполнение concatenate итеративно медленно, но делать одну копию в конце, объединяя все массивы в один, лучше. Но не стесняйтесь сравнивать альтернативы (на более мелких проблемах, если это необходимо). - person hpaulj; 05.11.2020
comment
Я чувствую, что это решение определенно более питоническое, но включает в себя немного больше передачи одних и тех же данных несколько раз. И если я назначу свой arr0 arr3, нарезав ваш arr, тогда они останутся в виде массивов, которые не являются смежными в памяти. Если я copy их, все должно быть в порядке. - person jms547; 05.11.2020