Встроенный метод для разделения массива NumPy - PullRequest
0 голосов
/ 29 декабря 2018

У меня большой объем данных в файлах NetCDF4, и я пытаюсь написать сценарий для динамического разделения этих данных на максимально возможное количество в памяти, выполнить вычисления и сохранить результаты, а затем перейти кследующий кусок

Пример того, что я пытаюсь сделать.Скажем, у меня есть такой массив:

import numpy as np
arr = np.random.randint(0, 10, (100, 15, 51))  # Call these x, y, and z coordinates

И я хочу читать одновременно только десять координат x, например:

placeholder = 0
for i in range(10, 101, 10):
    tmp_array = arr[placeholder:i, :, :]
    # Do calculations here and save results to file or database
    placeholder += 10

Есть ли какая-то встроеннаяв методе для этого?В этом простом примере это работает довольно хорошо, но по мере того, как все усложняется, мне кажется, что я могу справиться со всем этим самостоятельно.Я знаю о Dask, но в этой ситуации мне это не поможет, потому что я не выполняю операции с массивами с данными.Хотя Даск мог бы быть мне полезен, если бы у него были методы, чтобы справиться с этим тоже.

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

Документация Dask показывает, как создавать фрагментированные массивы только для того типа вычислений, который вы имеете в виду, для случая файлов hdf5: http://docs.dask.org/en/latest/array-creation.html#numpy-slicing.Ваш случай netCDF4 может работать или не работать одинаково, но раздел ниже о delayed поможет, если нет.

Создав ваш dask-массив, вы захотите использовать map_blocks метод для операции «что-то сделать с каждым чанком» (предполагается получить какой-либо вывод обратно), цикл по содержимому атрибута .blocks или использование .to_delayed() для выполнения произвольных действий с каждым фрагментом.Что именно вам подходит, зависит от того, чего вы хотите достичь.

0 голосов
/ 30 декабря 2018

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

def spliterate(buf, chunk):
    for start in range(0, buf.size, chunk):
        yield buf[start:start + chunk]

Использовать его довольно просто:

for tmp in spliterate(arr, 10):
    # do calculations on tmp, don't worry about bookkeeping
0 голосов
/ 29 декабря 2018

Вы можете использовать np.split, который принимает массив и либо размер куска, либо список индексов, по которым выполняется разделение.Ваш случай будет np.split(arr, 10), что даст вам список из 10 массивов формы (10, 15, 51).

Обратите внимание, что возникает исключение, если ось не может быть разделена поровну, например, если вы запросили куски размера9. Если вы хотите разделить на почти равные куски, без повышения, вы можете использовать np.array_split вместо.

...