Я долго боролся с этой проблемой в разных формах и так и не смог найти хорошего решения.
В принципе, если я хочу написать функцию, которая выполняет операцию над заданной, но произвольной осью произвольного массива рангов, в стиле (например) np.mean (A, axis = some_axis), я в целом понятия не имею как это сделать.
Проблема всегда, кажется, сводится к негибкости синтаксиса нарезки; если я хочу получить доступ к i-му срезу по 3-му индексу, я могу использовать A [:,:, i], но я не могу обобщить это до n-го индекса.
Вы не можете обобщать это. Фактически, в этом случае неплохо рассмотреть пример numpy.mean(a, axis=axis_index)
. Даже в numpy, который написан в основном на C, просматриваются индексы осей, чтобы знать, где вычислить среднее значение. Взгляните на reduction.c
, который находится в ядре numpy.mean
. Несмотря на то, что они форматируют данные перед выполнением операций, всегда требуется прокручивать все оси с помощью вашего axis_index
.
Для этого функции numpy
используют несколько подходов:
транспонировать оси для перемещения целевой оси в известное положение, обычно первое или последнее; и при необходимости транспонировать результат
изменить форму (вместе с транспонированием), чтобы уменьшить простоту проблемы. Если ваше внимание сосредоточено на n-м измерении, может не иметь значения, где размер (: n) сглаживается или нет. Они просто «плывут».
построить индексирующий кортеж. idx = (slice(None), slice(None), j); A[idx]
является эквивалентом A[:,:,j]
. Начните со списка или массива нужного размера, заполните фрагментами, возитесь с ними, а затем преобразуйте их в кортеж (кортежи неизменяемы).
Создавайте индексы с помощью инструментов indexing_tricks
, таких как np.r_
, np.s_
и т. д.
Изучите код, который предусматривает оси. Скомпилированный ufuncs
не поможет, но такие функции, как tensordot
, take_along_axis
, apply_along_axis
, np.cross
, написаны на Python и используют один или несколько из этих приемов.
Расширяя первое предложение @hpaulj, возможно, неожиданно результат после swapaxes-> некоторая операция по созданию нового массива-> swapaxes нового массива часто является смежным, см., Например, здесь