Давайте определим небольшую вспомогательную функцию, которая сопоставляет значение xx
с первым столбцом yy
и возвращает значение из второго.
def foo(x):
return yy[yy[:,0]==x, 1].item()
и протестируйте пару значений:
In [101]: foo(3)
Out[101]: 2
In [102]: foo(4)
Out[102]: 8
Вместо nditer
, давайте использовать xx.flat
в качестве 1d итератора.
In [103]: for x in xx.flat:
...: print(foo(x))
...:
8
6
2
5
Или сделать то же самое в понимании списка:
In [104]: [foo(x) for x in xx.flat]
Out[104]: [8, 6, 2, 5]
и используйте reshape
для приведения его обратно в массив той же формы, что и xx
:
In [105]: np.reshape([foo(x) for x in xx.flat],xx.shape)
Out[105]:
array([[8, 6],
[2, 5]])
Мне также нравится frompyfunc
как способ применения скалярной функции к элементам массива. В тестах это может быть в 2 раза быстрее, чем более прямые итерации, но все же легко использовать без ошибок:
In [106]: np.frompyfunc(foo,1,1)(xx)
Out[106]:
array([[8, 6],
[2, 5]], dtype=object)
Но другой ответ показывает, как сделать то же самое без итерации уровня Python.
Еще один «векторизованный» подход:
Сравните все значения xx
с 1-м столбцом yy
. В результате получается логический массив 3d:
In [107]: xx[...,None]==yy[:,0]
Out[107]:
array([[[False, False, True, False],
[ True, False, False, False]],
[[False, False, False, True],
[False, True, False, False]]])
where
- это кортеж из 3 элементов. 2 элемента индекса xx
, последний yy
:
In [108]: np.where(xx[...,None]==yy[:,0])
Out[108]: (array([0, 0, 1, 1]), array([0, 1, 0, 1]), array([2, 0, 3, 1]))
In [109]: yy[np.where(xx[...,None]==yy[:,0])[2],1]
Out[109]: array([8, 6, 2, 5])