Обычно функциональный или картографический подход не оптимален для numpy
. numpy
- это все о массивах, поэтому лучше всего подумать о строительных блоках всего массива, которые предоставляет numpy
. Они работают в скомпилированном коде.
Например, в вашем случае:
Определите массив:
In [10]: a = np.random.randint(0,10,9)
In [11]: a
Out[11]: array([6, 0, 2, 5, 0, 5, 2, 0, 1])
Сравните его с диапазоном значений n
- используя целоемассив ==
test (и broadcasting
. Результатом является логический массив, значение True / False для каждого (i, j):
In [12]: np.arange(8)[:,None]==a
Out[12]:
array([[False, True, False, False, True, False, False, True, False],
[False, False, False, False, False, False, False, False, True],
[False, False, True, False, False, False, True, False, False],
[False, False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False, False],
[False, False, False, True, False, True, False, False, False],
[ True, False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False, False]])
Учитывая, что его легко отобразить на(-1,1) значений. np.where
является лишь одним из таких способов:
In [13]: np.where(np.arange(8)[:,None]==a, 1, -1)
Out[13]:
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]])
Ближе к вашей идее карты, мы могли бы определить функцию, которая работает с парой скалярных значений:
def foo(i,x):
if i==x:
return 1
else:
return -1
и используйте np.vectorize
для создания функции, которая принимает 2 массива и передает пары скаляров этой функции.
In [16]: np.vectorize(foo)(np.arange(8)[:,None], a)
Out[16]:
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]])
Но это НАМНОГО медленнее, чем первый подход.
Подход к пониманию списка:
In [22]: [[(1 if i==x else -1) for x in a] for i in range(8)]
Out[22]:
[[-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]]
, который затем можно превратить в массив (это может быть на самом деле быстрее, чем подход vectorize
).