#python #arrays #numpy #search
#python #массивы #numpy #Поиск
Вопрос:
Я хочу создать массив с известными координатами из существующих данных, как избежать всех этих циклов, чтобы ускорить его? Пробовал с np.where, приблизился, но не попал туда. Спасибо!
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[0, 1, 3, 6], [0, 1, 2, 4], [0, 1, 2, 3]])
y = np.array([[0, 2, 0, 1], [1, 2, 1, 1], [2, 3, 2, 4]])
z = np.array([[100, 100, 100, 100], [100, 150, 100, 100], [100, 100, 100, 200]])
xx = np.arange(np.min(x), np.max(x) 1, 1)
yy = np.arange(np.min(y), np.max(y) 1, 1)
grid_x, grid_y = np.meshgrid(xx, yy)
L1, C1 = x.shape
L2, C2 = grid_x.shape
v = np.zeros((L2, C2))
n = np.zeros((L2, C2))
for l2 in range(L2):
for c2 in range(C2):
for l1 in range(L1):
for c1 in range(C1):
if grid_x[l2, c2] == x[l1, c1] and grid_y[l2, c2] == y[l1, c1]:
v[l2, c2] = v[l2, c2] z[l1, c1]
n[l2, c2] = n[l2, c2] 1
v = v/n
plt.imshow(v)
plt.show()
Комментарии:
1. добавьте фактический результат и ожидаемый или желаемый результат
2. Это возвращает желаемый результат, просто слишком медленно для работы с тысячами строк и столбцов.
3. Не могли бы вы подробнее рассказать о «подобрался близко, но не попал туда».
Ответ №1:
Есть 2 способа ускорить это:
- вы можете создавать большие и уродливые 4-размерные маски и применять их к своим сеткам (играя с
np.newaxis
и==
из 2 массивов np. - вы можете использовать Numba (http://numba.pydata.org/numba-doc/0.17.0/user/jit.html ) и вам вообще не нужно переписывать свой код. В основном он использует jit-компиляцию и делает ваш код почти таким же быстрым, как код numpy. Все, что вам нужно, это просто обернуть вашу функцию
@jit
декодератором. Обратите внимание, что не все функции могут быть скомпилированы таким образом. Вероятно (не уверен), вам нужно было бы переместить вложенные циклы в другую функцию и обернуть ее@jit
.
Ответ №2:
Частичное улучшение, пока сосредоточенное на n
, количестве совпадений.
import numpy as np
#import matplotlib.pyplot as plt
x = np.array([[0, 1, 3, 6], [0, 1, 2, 4], [0, 1, 2, 3]])
y = np.array([[0, 2, 0, 1], [1, 2, 1, 1], [2, 3, 2, 4]])
z = np.array([[100, 100, 100, 100], [100, 150, 100, 100], [100, 100, 100, 200]])
xx = np.arange(np.min(x), np.max(x) 1, 1)
yy = np.arange(np.min(y), np.max(y) 1, 1)
grid_x, grid_y = np.meshgrid(xx, yy)
L1, C1 = x.shape
L2, C2 = grid_x.shape
v = np.zeros((L2, C2),int)
n = np.zeros((L2, C2),int)
for l2 in range(L2):
for c2 in range(C2):
for l1 in range(L1):
for c1 in range(C1):
if grid_x[l2, c2] == x[l1, c1] and grid_y[l2, c2] == y[l1, c1]:
#v[l2, c2] = z[l1, c1]
n[l2, c2] = 1
# with broadcasting create 4d arrays, matching x and y with their grids
X = grid_x[:,:,None,None]==x[None,None,:,:]
Y = grid_y[:,:,None,None]==y[None,None,:,:]
XY = X amp; Y
XY = XY.sum(axis=(2,3))
#v = v/n
print(x)
print(y)
print(n)
print(XY)
XY
Матчи n
.
1032:~/mypy$ python3 stack63844601.py
[[0 1 3 6]
[0 1 2 4]
[0 1 2 3]]
[[0 2 0 1]
[1 2 1 1]
[2 3 2 4]]
[[1 0 0 1 0 0 0] # n
[1 0 1 0 1 0 1]
[1 2 1 0 0 0 0]
[0 1 0 0 0 0 0]
[0 0 0 1 0 0 0]]
[[1 0 0 1 0 0 0] # XY
[1 0 1 0 1 0 1]
[1 2 1 0 0 0 0]
[0 1 0 0 0 0 0]
[0 0 0 1 0 0 0]]
Это должно быть быстрее, чем итерация, хотя в более крупных случаях могут возникнуть проблемы с памятью.
grid_x
и grid_y
вероятно, это могут быть sparse
версии, хотя это не экономит память в промежуточных массивах 4d.
Я все еще не до конца понял, что должен делать этот поиск. На данный момент это своего рода подход грубой силы, использующий довольно поверхностное понимание ваших 4-уровневых вложенных циклов.
Комментарии:
1. Это проблема с сеткой, но без интерполяции. Есть 3 массива (их можно было бы сгладить, и у нас было бы только 2 цикла for), которые имеют x, y и z. Значения x и y являются точными значениями в узлах сетки, мы могли бы легко перейти от значений к индексам. Сетка строится из максимальных и минимальных значений x и y. Тогда возникает вопрос о том, чтобы поместить значения z в правильное место и выполнить среднее значение, когда в одном и том же месте их несколько.