numpy.ravel_multi_index

numpy.ravel_multi_index(multi_index, dims, mode='raise', order='C')

Функция ravel_multi_index() преобразует кортеж массивов индексов в плоский массив индексов.

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

Параметры:
multi_index - кортеж массивов NumPy или массивоподобных объектов.
Кортеж массивов индексов, в котором один массив индексирует соответствующую ось исходного массива.
dims - кортеж целых чисел.
Определяет форму массива, который индексируется массивами из multi_index.
mode - {'raise', 'wrap', 'clip'} (необязательный параметр).

Определяет метод обработки индексов, которые выходят за пределы формы исходного массива. Если указан один режим, то он применяется ко всем массивам в multi_index, но можно указать кортеж режимов аналогичной длинны, что бы обрабатывать каждый массив отдельно.

  • 'raise' - вызывать исключение (по умолчанию);
  • 'wrap' - обогнуть вокруг оси, т.е. циклически сместиться по ней;
  • 'clip' - обрезает до диапазона индексов исходного массива, причем отрицательные индексы обрезаются до 0.
order - {'C', 'F'} (необязательный параметр).
Определяет то каким образом рассматривать исходный массив, если 'C' - то это стандартный (уже привычный) массив данные в котором хранятся в строковом порядке (C-стиле), если 'F' - то это массив в столбчатом стиле Fortran.
Возвращает:
ndarray - массив NumPy
массив индексов элементов исходного массива в его сжатой до одной оси копии.
Смотрите так же:
unravel_index flat, flatten, ravel


Примеры

Допустим у нас есть двумерный массив и мы индексируем его следующим образом:

>>> import numpy as np
>>> 
>>> a = np.arange(0, 24, 2).reshape(3, 4)
>>> a
array([[ 0,  2,  4,  6],
       [ 8, 10, 12, 14],
       [16, 18, 20, 22]])
>>> 
>>> a[[0, 1, 2], [3, 2, 1]]
array([ 6, 12, 18])

Теперь, представим, что по какой то причине этот массив стал плоским:

>>> b = a.ravel()
>>> b
array([ 0,  2,  4, ..., 18, 20, 22])

Какими должны быть индексы элементов нового, плоского массива, что бы вытащить из него те же самые элементы? Именно на этот вопрос и отвечает функция ravel_multi_index:

>>> np.ravel_multi_index(([0, 1, 2], [3, 2, 1]), (3, 4))
array([3, 6, 9], dtype=int32)
>>> 
>>> b[[3, 6, 9]]
array([ 6, 12, 18])

Можно подумать, что каждый массив индексов должен быть одномерным, но это может быть любой допустимый массив индексов:

>>> a[[[1, 2], [0, 1]], [1, 2]]
array([[10, 20],
       [ 2, 12]])
>>> 
>>> np.ravel_multi_index(([[1, 2], [0, 1]], [1, 2]), (3, 4))
array([[ 5, 10],
       [ 1,  6]], dtype=int32)
>>> 
>>> b[[5, 10, 1, 6]]
array([10, 20,  2, 12])
>>> 
>>> b[np.ravel_multi_index(([[1, 2], [0, 1]], [1, 2]), (3, 4))]
array([[10, 20],
       [ 2, 12]])

Мы так же можем узнать индекс всего одного элемента:

>>> np.ravel_multi_index((1, 3), (3, 4))
7
>>> 
>>> a[1, 3]
14
>>> 
>>> b[7]
14

Очень редко, но все же приходится иметь дело с Fortran кодом, в котором массивы хранятся в столбчатом стиле. А в этом стиле строки являются столбцами а столбцы строками. Что бы индексировать такие массивы достаточно установить соответствующий флаг в параметре order:

>>> np.ravel_multi_index(([0, 1, 2], [3, 2, 1]), (3, 4))
array([3, 6, 9], dtype=int32)
>>> 
>>> np.ravel_multi_index(([0, 1, 2], [3, 2, 1]), (3, 4), order = 'F')
array([9, 7, 5], dtype=int32)

Случаи, в которых значения в массивах индексов выходят за пределы исходного индекса могут быть обработаны без вызова исключения (ошибки), для этого достаточно указать режим их обработки в параметре mode:

>>> np.ravel_multi_index(([1, 3], [1, 2]), (3, 4), mode = 'wrap')
array([5, 2], dtype=int32)
>>> 
>>> np.ravel_multi_index(([1, 3], [1, 2]), (3, 4), mode = 'clip')
array([ 5, 10], dtype=int32)