В основном я пытаюсь взять средневзвешенное значение набора 3D-данных, но только для отфильтрованного подмножества данных, где фильтр основан на другом (2D) массиве. Форма 2D-данных соответствует первым двум измерениям 3D-данных и, таким образом, повторяется для каждого среза в 3-м измерении.
Что-то вроде:
import numpy as np
myarr = np.array([[[4,6,8],[9,3,2]],[[2,7,4],[3,8,6]],[[1,6,7],[7,8,3]]])
myarr2 = np.array([[7,3],[6,7],[2,6]])
weights = np.random.rand(3,2,3)
filtered = []
for k in range(len(myarr[0,0,:])):
temp1 = myarr[:,:,k]
temp2 = weights[:,:,k]
filtered.append(temp1[np.where(myarr2 > 5)]*temp2[np.where(myarr2 > 5)])
average = np.array(np.sum(filtered,1)/len(filtered[0]))
Я беспокоюсь об эффективности здесь. Можно ли векторизовать это, чтобы мне не нужен цикл, или есть другие предложения, чтобы сделать это более эффективным?






Самая очевидная проблема с эффективностью, даже если не учитывать цикл, заключается в том, что np.where(...) вызывается несколько раз внутри цикла при одном и том же условии! Вы можете просто сделать это один раз заранее. Кроме того, нет необходимости в петле. Ваша операция в основном равна:
mask = myarr2 > 5
average = (myarr[mask] * weights[mask]).mean(axis=0)
np.where тоже не нужен.
myarr2 — это массив формы (i, j) с теми же первыми двумя размерами, что и myarr и weight, которые имеют некоторую форму (i, j, k).
Таким образом, если в логической маске n есть элементы myarr2 > 5 True, вы можете применить их к другим массивам для получения элементов (n, k) (взяв все элементы по третьей оси, когда в определенной позиции [i, j] есть значение True).