#python #arrays #numpy #vectorization
#Python #массивы #numpy #Векторизация
Вопрос:
У меня есть 3D-массив numpy. Я хотел бы сформировать новый 3D-массив, выполнив функцию для последовательных 2d-фрагментов вдоль оси и сложив полученные фрагменты вместе. Очевидно, что есть много способов сделать это; Я бы хотел сделать это как можно более кратким способом. Я бы подумал, что это было бы возможно с numpy.vectorize
помощью , но, похоже, это создает функцию, которая перебирает каждое значение в моем массиве, а не 2D-фрагменты, полученные путем перемещения вдоль первой оси.
В принципе, мне нужен код, который выглядит примерно так:
new3dmat = np.vectorize(func2dmat)(my3dmat)
И выполняет то же самое, что и это:
new3dmat = np.empty_like(my3dmat)
for i in range(my3dmat.shape[0]):
new3dmat[i] = func2dmat(my3dmat[i])
Как я могу это сделать?
Комментарии:
1. Вы не можете переписать свой
func2dmat
, чтобы работать с полным 3D-массивом? YMMV, но обычно это лучший способ выполнить этот тип векторизации..2. Я мог бы это сделать, но решение цикла предпочтительнее. Я хочу иметь возможность кратко оперировать составной структурой данных (3D-матрицей) с функцией, которая работает с ее составляющими (2d-матрицами) — и эта функция не должна нуждаться в знании более крупной структуры, из которой исходят эти составляющие. Таким образом, мне нужна только одна функция, а не специальные функции для каждой возможной структуры, содержащей 2d-матрицы.
3. Вам нужен GUFUNC, например, например
np.linalg.det
… Соглашение заключается в том, чтобы заставить вашу функцию работать с каждым 2D-массивом в последних 2 измерениях входных данных. Если вы можете написать для этого быстрый векторизованный код, заставить его работать по другим осям — это просто вопрос разумного использованияnp.rollaxis
и тому подобного. Решение цикла Python вряд ли когда-либо предпочтительнее, если вы хотите в полной мере использовать преимущества numpy.4. Предпочтительнее субъективно.. если срез достаточно большой, разница в производительности должна быть минимальной, а логика Sean верна; это не концептуальный бизнес внутренней функции, сколько, если таковые имеются, присутствуют другие оси. написание вашего кода для обработки этого общего случая, когда нет ощутимого преимущества в производительности, пахнет преждевременной оптимизацией.
5. @Jaime Мне нравится идея иметь функцию, которая работает по двум последним осям по соглашению. Спасибо за вашу помощь, пока что я использую решение Eelco.
Ответ №1:
Я боюсь, что что-то вроде приведенного ниже — лучший компромисс между лаконичностью и производительностью. к сожалению, apply_along_axis не принимает несколько осей.
new3dmat = np.array([func2dmat(slice) for slice in my3dmat])
Это не идеально с точки зрения дополнительных выделений и так Далее, Но если .shape[0] не является большим по сравнению с .size , дополнительные накладные расходы должны быть минимальными.
Комментарии:
1. Хм, это выглядит нормально. Мне интересно, есть ли способ выполнить
slice in my3dmat
итерацию по оси, отличной от первой?2. вы можете использовать np.rollaxis, чтобы перенести нужную ось для итерации на передний план