Need to compare two arrays elements inside a for loop in Python 3 and getting error "The truth value of an array ..."

1k Views Asked by At

I have a numpy array in the form:

y_sol = 
[[0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]
 ...
 [1. 0. 0.]
 [0. 1. 0.]
 [1. 0. 0.]]

and I need to translate it for a categorical string value using correlations given by a list of tuples:

transf_codes = [('Alert', [1., 0., 0.]),     
                ('Neutral', [0., 1., 0.]),     
                ('Urgent', [0., 0., 1.])]   

Note that I haven't used a dictionary here to avoid a complication to search for keys having the values as the search input.

Anyhow, I've tried the following code to have the job done:

for i in np.arange(len(y_sol)-1): 
    for j in np.arange(3):
        if np.equal(transf_codes[j][1], y_sol[i].all()):  # <-error line 
            y_categ[i] = transf_codes[j][0] 

and I get the error "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"

In the "if" line above, the more natural form >>> transf_codes[j][1] == y_sol[i] <<<, with or without .all() or .any(), raises the same error.

What is the righ and best approach to compare element-wise of arrays, lists, etc. in an if-statement?

Many thanks in advance.

1

There are 1 best solutions below

2
On

The error you are seeing happens whenever numpy tries to cast an array as a boolean. It doesn't understand how to do so, so it throws that error.

So when you do something like if (a == b) with a, b being arrays, you wind up with an error.

However, a == b will yield a boolean array, with the element-wise comparison. Note that for that to happen a, b have to be numpy arrays. List behaviour is different.

One way we could use the boolean array is with the np.all method which I see you used, but not in the right place. You currently do .all() on the y_sol[i].

So the following code and output are the correct.

import numpy as np
y_sol = np.array( \
[[0., 0., 1.],
 [0., 0., 1.],
 [0., 0., 1.],
 [1., 0., 0.],
 [0., 1., 0.],
 [1., 0., 0.]])

transf_codes = [('Alert', [1., 0., 0.]),
                ('Neutral', [0., 1., 0.]),
                ('Urgent', [0., 0., 1.])]

for i in np.arange(len(y_sol)-1):
    for j in np.arange(3):
        if (transf_codes[j][1] == y_sol[i]).all():  # <-error line
            print(f'y_sol[i]={y_sol[i]}, transf_codes={transf_codes[j][0]}')

And this outputs:

y_sol[i]=[0. 0. 1.], transf_codes=Urgent
y_sol[i]=[0. 0. 1.], transf_codes=Urgent
y_sol[i]=[0. 0. 1.], transf_codes=Urgent
y_sol[i]=[1. 0. 0.], transf_codes=Alert
y_sol[i]=[0. 1. 0.], transf_codes=Neutral

Note that I used .all() after having compared the vectors.