Транслировать массивы в одинаковую форму, затем получить минимум по одной оси

У меня есть 3 массива numpy с разными формами (один даже не массив, а скаляр) или размерами.

arr1.shape
# (3, 3, 11)
arr2  # this is the scalar
# 1
arr3.shape
# (3, 11)

Я хочу вычислить минимум по определенной оси.

Я пробовал как это:

np.minimum.accumulate([arr1, np.expand_dims(arr2, axis=(0,1,2)), np.expand_dims(arr3, axis=1)])

Результат:

VisibleDeprecationWarning: создание ndarray из рваных вложенных последовательности (которые представляют собой список-или-кортеж списков-или-кортежей-или ndarrays с разной длиной или формой) не рекомендуется. Если вы хотели сделать это, вы должны указать 'dtype=object' при создании файла ndarray.
ValueError: истинное значение массива с более чем одним элементом двусмысленный. Используйте a.any() или a.all()

Я думал, что это сработает, потому что это соответствует правилам вещания

Два измерения совместимы, когда
1. они равны, или
2. один из них 1.

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

# adding works as a proof that broadcasting works
arr1 + np.expand_dims(arr2, axis=(0,1,2)) + np.expand_dims(arr3, axis=1)

Я достигаю того, чего хочу, следующим образом, но мне кажется, что это неправильный подход. Почему я должен «вручную» транслировать массивы в одну и ту же форму, когда мне не нужно делать это с помощью «обычных» математических операций, таких как сложение и вычитание. Я что-то упустил или это уже самый "чистый" способ сделать это?

np.array(np.broadcast_arrays(arr1, np.expand_dims(arr2, axis=(0,1,2)), np.expand_dims(arr3, axis=1))).min(axis=0)

Хочу добавить, что знаю о np.minimum(). Но это позволяет только «сравнение» двух массивов. Я хочу передать несколько массивов.

Можете ли вы точно объяснить, что вы имеете в виду, я хочу вычислить минимум по определенной оси? Можете ли вы показать, какой результат вы ожидаете?

Buzz 17.04.2023 17:26

У вас всего 3 массива, лучше сделайте np.minimum(np.minimum(a1,a2), a3[:,None]).

Quang Hoang 17.04.2023 17:33

Сначала убедитесь, что это работает: np.array([arr1, np.expand_dims(arr2, axis=(0,1,2)), np.expand_dims(arr3, axis=1)]). Я подозреваю, что именно это вызывает предупреждение ragged.

hpaulj 17.04.2023 18:45
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

np.minimum.accumulate (или любой ufunc accumulation) сначала делает массив из входного списка. Вот что дает предупреждение о рваном массиве

Если добавить object dtype по мере необходимости, получится массив из 3 элементов, причем массивы элементов различаются по форме:

In [92]: np.array([arr1, np.expand_dims(arr2, axis=(0,1,2)), np.expand_dims(arr3, axis=1)],object)
Out[92]: 
array([array([[[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],

              [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]],

              [[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
               [1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]]]),
       array([[[1]]]),
       array([[[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]],

              [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]],

              [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]])],
      dtype=object)

np.add может работать с этим массивом из 3 элементов:

In [104]: np.add.reduce(_92).shape
Out[104]: (3, 3, 11)
In [105]: np.add.accumulate(_92).shape
Out[105]: (3,)

minumum, уменьшать или накапливать, дайте эту ошибку двусмысленности:

In [106]: np.minimum.reduce(_92).shape
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[106], line 1
----> 1 np.minimum.reduce(_92).shape

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Это означает, что он сравнивает два массива и получает логический массив.

np.minimum(_92[0],_92[1]) работает, но np.minimum.reduce(_92[0,1]) выдает эту ошибку. Это почти как если бы он делал что-то вроде if или or/and на парах; но это скрыто в скомпилированном коде.

С помощью broadcast_arrays вы создаете массив 4d, допуская нормаль min на оси:

In [117]: np.array(np.broadcast_arrays(arr1, np.expand_dims(arr2, axis=(0,1,2)), np.expand_dims(arr3, axis=1))).shape
Out[117]: (3, 3, 3, 11)

Другие вопросы по теме