Преобразование многомерного массива в 2D и последующее индексирование - PullRequest
1 голос
/ 24 мая 2019

У меня есть некоторый код, который по логике лучше всего настроить как сильно вложенные массивы. Общая структура имеет большие размеры и разреженную, поэтому мне пришлось преобразовать ее в 2-мерную матрицу в соответствии с требованиями разреженной реализации, чтобы она помещалась в памяти.

Теперь я мысленно переключаюсь между двумя форматами, что сложно и запутанно. Я написал небольшую функцию, которая из вложенных входных данных будет вычислять 2d-ячейку, но если я захочу выполнить запрос диапазона, это будет намного сложнее.

import numpy as np

dim1 = 1
dim2 = 2
dim3 = 3
dim4 = 4 
dim5 = 5
dim6 = 6

sixD = np.arange(720).reshape(dim1, dim2, dim3, dim4, dim5, dim6)

twoD = sixD.transpose(0,1,2,3,4,5).reshape(dim1,-1)

def sixDto2DCell(a, b, c, d, e, f):
  return [a, (b*dim3*dim4*dim5*dim6) + 
    (c*dim4*dim5*dim6) + 
    (d*dim5*dim6) + 
    (e*dim6) + 
    f]

x, y = sixDto2DCell(0, 1, 2, 3, 4, 5)
assert(sixD[0, 1, 2, 3, 4, 5] == twoD[x, y])

поэтому я пытаюсь понять, что я буду делать для запроса типа

sixD[0, 1, 0:, 3, 4, 5]

для возврата тех же значений в 2-й матрице

Нужно ли мне писать новую функцию или я пропустил встроенный простой способ достижения того же самого?

Любая помощь будет принята с благодарностью: -)

1 Ответ

1 голос
/ 24 мая 2019

Подход № 1

Вот один из способов общего извлечения данных из 2D-разреженной матрицы или любого 2D-массива по этому вопросу с соответствующим n-dim-массивом и его начальными и конечными индексами вдолькаждая ось -

def sparse_ndim_map_indices(ndim_shape, start_index, end_index):       
    """
    Get flattened indices for indexing into a sparse array mapped to
    a corresponding n-dim array.
    """        

    # Get shape and cumulative shape info for use to get flattened indices later
    shp = ndim_shape
    cshp = np.r_[np.cumprod(shp[::-1])[::-1][1:],1]

    # Create open-ranges
    o_r = np.ix_(*[s*np.arange(i,j) for (s,i,j) in zip(cshp,start_index,end_index)])

    id_ar = np.zeros(np.array(end_index) - np.array(start_index), dtype=int)
    for r in o_r:
        id_ar += r
    return id_ar

Использование предоставленной выборки для изучения пробного прогона -

In [637]: start_index = (0,1,1,1,4,3)
     ...: end_index =   (1,2,3,4,5,6)
     ...: 
     ...: out1 = sixD[0:1, 1:2, 1:3, 1:4, 4:5, 3:6]

In [638]: out1
Out[638]: 
array([[[[[[537, 538, 539]],

          [[567, 568, 569]],

          [[597, 598, 599]]],


         [[[657, 658, 659]],

          [[687, 688, 689]],

          [[717, 718, 719]]]]]])

In [641]: idx = sparse_ndim_map_indices(sixD.shape, start_index, end_index)

In [642]: twoD[:,idx.ravel()]
Out[642]: 
array([[537, 538, 539, 567, 568, 569, 597, 598, 599, 657, 658, 659, 687,
        688, 689, 717, 718, 719]])

Подход № 2

Вот еще однасоздание всех комбинаций индексов вдоль каждой оси с последующим использованием np.ravel_multi_index для получения индексов плоского конца -

import itertools

def sparse_ndim_map_indices_v2(ndim_shape, start_index, end_index):    
    # Create ranges and hence get the flattened indices
    r = [np.arange(i,j) for (i,j) in zip(start_index,end_index)]
    return np.ravel_multi_index(np.array(list(itertools.product(*r))).T, ndim_shape)
...