This question already has answers here:
How do Python's any and all functions work?
(10 answers)
Closed 2 years ago.
I'm trying to write a script that simulates a system of chemical reactions over time. One of the inputs to the function is the following array:
popul_num = np.array([200, 100, 0, 0])
Which contains the number of discrete molecules of each species in the system. Part of the main function has an if statement that's meant to check that number of molecules is positive. if it is processed to the next iteration, else break out of the whole simulation
if popul_num.any() < 0: # Any method isn't working! --> Does .any() work on arrays or just lists?
print("Break out of loop negative molecule numbers")
tao_all = tao_all[0:-1]
popul_num_all = popul_num_all[0:-1]
else:
break
I've used the .any() to try find if any element of the popul_num array is negative. But it doesn't work, it doesn't throw an error, the system just never enters the if statement and I can't figure out why?
I've just ran the program and the final number of molecules the system returned was: [135 -19 65 54] the program should have broken out before the second element got to -19.
Any suggestions?
Cheers
You should use .any() on a boolean array after doing the comparison, not on the values of popul_num themselves. It will return True if any of the values of the boolean array are True, otherwise False.
In fact, .any() tests for any "truthy" values, which for integers means non-zero values, so it will work on an array of integers to test if any of them are non-zero, which is what you are doing, but this is not testing the thing that you are interested in knowing. The code then compounds the problem by doing an < 0 test on the boolean value returned by any, which always evaluates True because boolean values are treated as 0 and 1 (for False and True respectively) in operations involving integers.
You can do:
if (popul_num < 0).any():
do_whatever
Here popul_num < 0 is a boolean array containing the results of element-by-element comparisons. In your example:
>>> popul_num < 0
array([False, False, False, False], dtype=bool)
You are, however, correct to use array.any() (or np.any(array)) rather than using the builtin any(). The latter happens to work for a 1-d array, but would not work with more dimensions. This is because iterating e.g. over a 4d array (which is what the builtin any() would do) gives a sequence of 3d arrays, not the individual elements.
There is also similarly .all(). The above test is equivalent to:
if not (popul_num >= 0).all():
The any method of numpy arrays returns a boolean value, so when you write:
if popul_num.any() < 0:
popul_num.any() will be either True (=1) or False (=0) so it will never be less than zero. Thus, you will never enter this if-statement.
What any() does is evaluate each element of the array as a boolean and return whether any of them are truthy. For example:
>>> np.array([0.0]).any()
False
>>> np.array([1.0]).any()
True
>>> np.array([0.0, 0.35]).any()
True
As you can see, Python/numpy considers 0 to be falsy and all other numbers to be truthy. So calling any on an array of numbers tells us whether any number in the array is nonzero. But you want to know whether any number is negative, so we have to transfrom the array first. Let's introduce a negative number into your array to demonstrate.
>>> popul_num = np.array([200, 100, 0, -1])
>>> popul_num < 0 # Test is applied to all elements in the array
np.ndarray([False, False, False, True])
>>> (popul_num < 0).any()
True
You asked about any on lists versus arrays. Python's builtin list has no any method:
>>> [].any()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'any'
There is a builtin function (not method since it doesn't belong to a class) called any that serves the same purpose as the numpy .any method. These two expressions are logically equivalent:
any(popul_num < 0)
(popul_num < 0).any()
We would generally expect the second one to be faster since numpy is implemented in C. However only the first one will work with non-numpy types such as list and set.
any() is a method for use on iterables. It returns True if any of the items in the iterable are truthy. You want something more like:
if any([True for x in popul_num if x > 0]):
print("at least one element was greater than zero!")
any() returns True, if at least one of the elements is True:
L1 = [False, False, False]
any(L1)
# >>> False
L1 = [True, False, False]
any(L1)
# >>> True
L1 = ["Hi", False, False]
any(L1)
# >>> True
L1 = []
any(L1)
# >>> False
any() returns True if at least one element in a NumPy array evaluates to True and np.all test whether all array elements along a given axis evaluate to True. What you need to solve your problem is the all method.
Related
I've been tinkering a little with Python operators and came across something I'm not sure about.
If I perform a bitwise operation (&, |) on 2 integers I will get unsurprisingly their bitwise value.
Meaning:
>>> a = 11
>>> b = 3
>>> a & b
3
This is because it performs bitwise AND on the binary representation of these numbers.
However, if I use the built in and operator I will get the second variable, irrespective of its type:
>>> b and a
11
>>> 'b' and 'a'
'a'
Why is it so?
Logical operators operate on the truthiness of an object. Every object has truth value, unless it has a __bool__ method that is explicitly overridden to raise an error. The major difference between a and b (logical) and a & b (bitwise) is that the former apply to any objects, while the latter only apply to numeric types that support bitwise operations1.
Python's logical operators are specifically designed to return the result of the last object evaluated:
a and b: Returns a Falsy a, or b (if a is truthy)
a or b: Returns a Truthy a, or b (if a if falsy)
From the tutorial:
The Boolean operators and and or are so-called short-circuit operators: their arguments are evaluated from left to right, and evaluation stops as soon as the outcome is determined. For example, if A and C are true but B is false, A and B and C does not evaluate the expression C. When used as a general value and not as a Boolean, the return value of a short-circuit operator is the last evaluated argument.
This property is used semi-idiomatically to check values before accessing them. For example, if a list must contain an element, you can do something like
if x and x[0] == value:
# ...
This will not raise an error, because if x is Falsy (empty), the and expression will return x instead of x[0] == value.
1 Set-like objects also support & as the intersection operator. This is conceptually similar to what the bitwise operator does for integers (you can think of bits as sets), and in no way detracts from the rest of the answer.
The documentation says:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Since Python considers the boolean value for both strings and non-zero integers to be True, x and y would imply True and True, and since the boolean of the first statement is not False, the second statement is evaluated and the resulting value (which is the value of the second term) is returned.
The first case with and:
>>> b and a #(11 and 3, both the values evaluates to be true because non-zero)
11
>>> 'b' and 'a' #(again both are evaluated to be true because non-empty)
For and all the conditions need to be True, so checked upto the last item if the previous evaluates to be True, hence you get the last item.
Case 1 : A and B
here consider A ,B both are non zeroes for and it checks both A,B that is it first evaluates A if in A after conversion in binary(for understanding consider positive integers , A > 0 and B > 0) whether 1 is present or not , if yes it moves to B and returns B as output. Because and checks both A and B.
A or B
here it checks the A as same as above if it has 1 after converting in to binary,
if A is True it return A (obviously A > 0 so it return A only ).
case 2 : suppose Any 1 in A,B or both A,B are ZEROES
I will try to explain in better way . I hope we all know truth tables for 'AND' and 'OR' and 'XOR'.
Same thing happening here just replace 1's and 0's with any number, if you want you use only 1's and 0's to understand in better way.
I have a simple numpy 2D Array. E.g. :
M=np.array([[15,1,0],
[19,5,2]])
which I loop over to check if in each line (axis 1)
a value exist greater than e.g. 2.
As the first value is always greater than 2, I slice the array to only check which of the other n values in that line is greater than 2.
#A
for i in range(len(M)):
if any(M[i,1:])>=2:
disp('Super')
Or, as I am not so familiar with python yet, I also used this code, which should function the same, right?
#B
for i in range(len(M)):
if any(x>=2 in x in M[i,1:]):
disp('Great')
The Problem I have now is that the any does not care about my slicing (M[i,1:]). It checks always the total array and of course finding a value greater than 2.
I expected in the first itteration a FALSE and in the second a TRUE
any(l) takes a list (or iterable) of values and returns True if any of the values it iterated over are truthy i.e. bool(value) == True. Therefore, it doesn't make sense to compare the output of any(...) with a number so I wouldn't do any(M[i,1:])>=2.
However, you can do any(M[i, 1:] > 2) where M[i, 1:] > 2 broadcasts the greater than operator to each value of the given row and returns you a boolean array that any can operate over.
What is the significance of the return part when evaluating functions? Why is this necessary?
Your assumption is right: dfdx[0] is indeed the first value in that array, so according to your code that would correspond to evaluating the derivative at x=-1.0.
To know the correct index where x is equal to 0, you will have to look for it in the x array.
One way to find this is the following, where we find the index of the value where |x-0| is minimal (so essentially where x=0 but float arithmetic requires taking some precautions) using argmin :
index0 = np.argmin(np.abs(x-0))
And we then get what we want, dfdx at the index where x is 0 :
print dfdx[index0]
An other but less robust way regarding float arithmetic trickery is to do the following:
# we make a boolean array that is True where x is zero and False everywhere else
bool_array = (x==0)
# Numpy alows to use a boolean array as a way to index an array
# Doing so will get you the all the values of dfdx where bool_array is True
# In our case that will hopefully give us dfdx where x=0
print dfdx[bool_array]
# same thing as oneliner
print dfdx[x==0]
You give the answer. x[0] is -1.0, and you want the value at the middle of the array.`np.linspace is the good function to build such series of values :
def f1(x):
g = np.sin(math.pi*np.exp(-x))
return g
n = 1001 # odd !
x=linspace(-1,1,n) #x[n//2] is 0
f1x=f1(x)
df1=np.diff(f1(x),1)
dx=np.diff(x)
df1dx = - math.pi*np.exp(-x)*np.cos(math.pi*np.exp(-x))[:-1] # to discard last element
# In [3]: np.allclose(df1/dx,df1dx,atol=dx[0])
# Out[3]: True
As an other tip, numpy arrays are more efficiently and readably used without loops.
I am new in python syntax.
I want to sum 5 arrays (boolean, have value of pixels 1 or 0) and put the the final large value of pixel(5) == 1, others values == 0.
resArraySum = np.array(5, (first | second | third | fourth | fifth), 1, 0)
print resArraySum
This is not correct.
If I did understood properly, you want to add 5 arrays and then create a mask where the pixels sum 5. I see here some miss-concepts that have nothing to do with python and its syntax.
First, booleans in python are defined as True and False, 0 and 1 are just integers with no boolean property (not entirely true if you compare them bitewise, but lets just leave this for now).
Second, what you are looking for is just the logical and operator, summing 5 arrays of 0 and 1 and then finding the indexes that sum to 5 is a bit overhead, you could just directly compare them logically.
The pseudo-code would look like this:
For small number of masks:
result = bool_mask[0] & bool_mask[1] & bool_mask[2] & bool_mask[3]
For a large number of masks:
# bool_mask = [a, b, c, d, e, f....] number of boolean arrays
result = bool_mask[0] # Equivalent to:
for mask in bool_mask[1:]: # for i in range(1, len(bool_mask)):
result &= mask # result &= bool_mask[i]
With N the number of masks and bool_mask a list containing the boolean arrays that you want to compare.
So, the first thing you have to do, is to properly create a boolean array. With numpy you can do that in a variety of different ways:
Creating it:
>>> A = np.array([1, 0, 1], dtype=np.bool) # will cast 1 to True and 0 to False
>>> A
array([ True, False, True], dtype=bool)
Converting it:
>>> A = np.array([1, 0, 1], dtype=int) # An integer array with 0 and 1
>>> A = A.astype(np.bool)
>>> A
array([ True, False, True], dtype=bool)
Comparing it:
>>> A = np.array([1, 0, 1], dtype=int) # Same int array
>>> A = A > 0.5
>>> A
array([ True, False, True], dtype=bool)
After you have your boolean arrays made truly boolean, either any of the pseudocode (it is real working code tho) above would work just fine.
Afterwards, if you will end up with an array result of type np.bool (boolean) with True values where all the masks intersect and False elsewhere. If you really want to go back to the 0 and 1 values, you could just cast the result down:
result = result.astype(int)
And True will be mapped to 1 while False to 0. Other ways of doing similar things would be:
result = result * 1
Any kind of numerical operations in numpy will cast a boolean array to integers.
Now, you will find (as mentioned above), that although 1 and 0 arrays are not boolean arrays, same and & operator will make bite-wise comparisons that would end up behaving like boolean arrays (as long as they only contain 1 and 0 values). Thus,
result = a & b & c & d
would work for both integer (with only 1 and 0) and boolean arrays. However, I would suggest using boolean arrays whether possible, as many interesting features of numpy such as boolean indexing only work if the arrays are truly boolean (an integer array of 0 and 1 would behave very differently that what you would expect).
I have one vector called cm which does not change
cm = np.array([[99,99,0]])
and another vector called pt. that I want to loop through certain values. but when the two are equal, I want it skip over and not perform the operation. for the sake of this post I just said to have it print out the value of pt, but I actually have a whole host of operations to run. here is my code
for i in range (95,103):
for j in range (95,103):
pt = np.array([[i,j,0]])
if pt == cm:
continue
print pt
i have tried changing the 4th line to
if pt.all == cm.all
but that prints everything, including the one I want to skip
and then if i turn it into
if pt.all() == cm.all()
that also doesn't work. what is the difference between those two anyway?
does anyone know how i can fix it so that when pt = [99,99,0] it will skip the operations and go back to the beginning of the loop? Thanks!
You're probably looking for (pt == cm).all(), although if floats are involved np.allclose(pt, cm) is probably a better idea in case you have numerical errors.
(1) pt.all == cm.all
This checks to see whether the two methods are equal:
>>> pt.all
<built-in method all of numpy.ndarray object at 0x16cbbe0>
>>> pt.all == cm.all
False
(2) pt.all() == cm.all()
This checks to see see whether the result of all matches in each case. For example:
>>> pt
array([[99, 99, 0]])
>>> pt.all()
False
>>> cm = np.array([10, 10, 0])
>>> cm.all()
False
>>> pt.all() == cm.all()
True
(3) (pt == cm).all()
This creates an array testing to see whether the two are equal, and returns whether the result is all True:
>>> pt
array([[99, 99, 0]])
>>> cm
array([[99, 99, 0]])
>>> pt == cm
array([[ True, True, True]], dtype=bool)
>>> (pt == cm).all()
True
One downside is that this constructs a temporary array, but often that's not an issue in practice.
Aside: when you're writing nested loops with numpy arrays you've usually made a mistake somewhere. Python-level loops are slow, and so you lose a lot of the benefits you get from using numpy in the first place. But that's a separate issue.