Reputation: 1103
So given number n
and an array a
, we need to create a n
by len(a)
matrix where the i,j
th entry of the matrix is 1
if i
equals to j
th entry of a
and -1
otherwise. Namely for each numbers i
from 0
to n-1
, we need to have an array that tell us if the number i
is equal to the array a
.
It would be cool if we had map feature like in functional programming. Then I could just create the rows by checking for each elements in array a
if that element equals the given number or not.
So is there a feature that I can use as shown below?
result=[]
for i in range(n):
result=np.vstack(result, np.map(checkequals(x,i),a)
return result
Upvotes: 0
Views: 50
Reputation: 231385
Generally a functional or mapping approach is not optimal with numpy
. numpy
is all about arrays, so it's best to think in terms of the whole-array building blocks that numpy
provides. Those operate in compiled code.
For example with your case:
Define an array:
In [10]: a = np.random.randint(0,10,9)
In [11]: a
Out[11]: array([6, 0, 2, 5, 0, 5, 2, 0, 1])
Compare it with the range of n
values - using whole array ==
test (and broadcasting
. The result is a boolean array, a True/False value for each (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]])
Given that, it's easy to map it onto a (-1,1) values. np.where
is just one such way:
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]])
Closer to your map idea, we could define a function that operates on a pair of scalar values:
def foo(i,x):
if i==x:
return 1
else:
return -1
and use np.vectorize
to make a function that takes 2 arrays, and passes pairs of scalars to this function.
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]])
But this is MUCH slower than the first approach.
A list comprehension approach:
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]]
which can then be made into an array (this may actually be faster than the vectorize
approach).
Upvotes: 1
Reputation: 922
Python2 has a built in map function, and so does python3. Numpy has vectorize
Upvotes: 0