Разделите каждое измерение на разные номера из списка в numpy

#python #numpy #numpy-ndarray

#python #numpy #numpy-ndarray

Вопрос:

У меня есть ndarray с формой (3,3,3) и список с 3 числами.

Я хочу разделить первое измерение на первое число в списке, второе измерение на второе число и третье измерение на третье число.

Пример:

 np.random.rand(3,3,3)

>>>array([[[0.90428811, 0.60637664, 0.45090308],
        [0.17400851, 0.49163535, 0.62370288],
        [0.58701608, 0.91207839, 0.69364496]],

       [[0.85290321, 0.85170489, 0.48792597],
        [0.02602198, 0.91088298, 0.14882673],
        [0.63354821, 0.21764451, 0.30760075]],

       [[0.64833375, 0.13583598, 0.50561519],
        [0.42832468, 0.91146014, 0.41627495],
        [0.71238947, 0.37868578, 0.05874898]]])
 

и список:

 lst=[0.215, 0.561,0.724]
 

Я хочу, чтобы результат вывода был результатом этого:

 [0.90428811/0.215, 0.60637664/0.215, 0.45090308/0.215],
        [0.17400851/0.215, 0.49163535/0.215, 0.62370288/0.215],
        [0.58701608/0.215, 0.91207839/0.215, 0.69364496/0.215]],

[[0.85290321/0.561, 0.85170489/0.561, 0.48792597/0.561],
        [0.02602198/0.561, 0.91088298/0.561, 0.14882673/0.561],
        [0.63354821/0.561, 0.21764451/0.561, 0.30760075/0.561]],

 [[0.64833375/0.724, 0.13583598/0.724, 0.50561519/0.724],
        [0.42832468/0.724, 0.91146014/0.724, 0.41627495/0.724],
        [0.71238947/0.724, 0.37868578/0.724, 0.05874898/0.724]]])
 

Я пытался сделать что-то подобное (arr — это ndarray).:

 nums=np.arange(3)

for n in nums:
    arr[i]=arr[i]/lst[i]
 

но получил ошибку:

Ошибка IndexError: допустимыми индексами являются только целые числа, срезы ( : ), многоточие ( ... ), numpy.newaxis ( None ) и целочисленные или логические массивы

Комментарии:

1. Возможно, вы сможете сделать это с помощью einsum

Ответ №1:

Просто сделайте это. Он передает lst массив, чтобы иметь форму (3, 1, 1) , которая легко сочетается с формой a .

Обратите внимание, что None это просто псевдоним для np.newaxis .

 import numpy as np
a = np.random.randn(3,3,3)
lst = np.array([0.215, 0.561,0.724])

a / lst[:, None, None]
 

Комментарии:

1. это сработало! единственное, что я не уверен, что понял, это то, как он не делит все измерения на числа в lst, как он узнает, чтобы «применить» его к правильному измерению

2. Я прикрепил ссылку на numpy broadcasting в своем ответе. По сути, он виртуально копирует элементы для создания lst массива формы (3, 3, 3) (3, 1, 1) для выполнения поэлементного деления. Вы можете заглянуть по ссылке, чтобы узнать больше о том, как работает вещание, и привести больше примеров. Не стесняйтесь обращаться за дальнейшими разъяснениями.

Ответ №2:

Используйте широковещательную передачу индекса:

 a = np.random.rand(3,3,3)
res = a / lst[:, np.newaxis, np.newaxis]
 

Причина, по которой это работает, заключается в том, что lst[:, np.newaxis, np.newaxis] генерируется массив с формой (3, 1, 1), а numpy расширяет любое измерение размером один до требуемого размера (путем повторения элемента) для многих распространенных операций. Этот процесс называется широковещательной передачей.

Итак, в нашем примере здесь для деления результат lst[:, np.newaxis, np.newaxis] будет расширен до:

 [[[0.215, 0.215, 0.215],
  [0.215, 0.215, 0.215],
  [0.215, 0.215, 0.215]],

 [[0.561, 0.561, 0.561],
  [0.561, 0.561, 0.561],
  [0.561, 0.561, 0.561]],

 [[0.724, 0.724, 0.724],
  [0.724, 0.724, 0.724],
  [0.724, 0.724, 0.724]]]
 

Обратите внимание, что это расширение происходит только концептуально, и numpy не будет выделять больше памяти только для того, чтобы снова и снова заполнять ее одним и тем же значением.

Ответ №3:

Это не очень красивое решение (из-за lst объявления), но оно работает:

 import numpy as np

np.random.rand(3,3,3)

arr = np.array([[[0.90428811, 0.60637664, 0.45090308],
        [0.17400851, 0.49163535, 0.62370288],
        [0.58701608, 0.91207839, 0.69364496]],

       [[0.85290321, 0.85170489, 0.48792597],
        [0.02602198, 0.91088298, 0.14882673],
        [0.63354821, 0.21764451, 0.30760075]],

       [[0.64833375, 0.13583598, 0.50561519],
        [0.42832468, 0.91146014, 0.41627495],
        [0.71238947, 0.37868578, 0.05874898]]])
        
lst = [[[0.215]], [[0.561]],[[0.724]]]

div = np.divide(arr, lst)

print(div)
 

Вывод будет:

 [[[4.20599121 2.82035647 2.09722363]
  [0.80934191 2.28667605 2.90094363]
  [2.73030735 4.24222507 3.22625563]]

 [[1.52032658 1.51819053 0.86974326]
  [0.04638499 1.62367733 0.26528829]
  [1.12931945 0.38795813 0.54830793]]

 [[0.8954886  0.18761876 0.69836352]
  [0.59160867 1.25892285 0.5749654 ]
  [0.98396336 0.52304666 0.081145  ]]]