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.
Related
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.
I don't know how to get an array of Boolean values, indexed by integers 2 to n.
I tried the following code, and it works, but I think it is stupid, and there must be something better. By the way, I first thought I don't need to write the very first two insert calls, but it seems in python that even if I write exactly insert(2, True), python will just put True in my first element of the array, in other words, a[0] = True not a[2] = True.
a = []
a.insert(0, 1)
a.insert(1, 1)
for index in range(2, n + 1):
a.insert(index, True)
I am seeking for another easy and inspiring way to implement this [an array of Boolean values, indexed by integers 2 to n]
Edit: I tried to write the pseudocode from https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes,
Input: an integer n > 1.
Let A be an array of Boolean values, indexed by integers 2 to n,
initially all set to true.
for i = 2, 3, 4, ..., not exceeding √n:
if A[i] is true:
for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n:
A[j] := false.
Output: all i such that A[i] is true.
as you can see, I just need a list that starts at index 2. I know how to do this algorithm, but I just felt that my way of creating [an array of Boolean values, indexed by integers 2 to n] is not good.
Python lists are always indexing from zero. If you want to create a list with True's from 2 to N, you can create something like this:
N = 5
a = [None] * 2 + [True] * (N-2)
[None, None, True, True, True]
And use only indices 2 or more later in your code.
So I'm currently trying to implement a perceptron, and I have two NumPy arrays, dimensions are 1x200. I would like to check each and every element in the two matrices against each other, and get back the sum of the elements which doesn't match each other. I tried doing something like this:
b = (x_A > 0).astype(int)
b[b == 0] = -1
Now I want to compare this matrix with the other, my question is therefore, is there a way to avoid for-loops and still get what I want (the sum of elements which doesn't match)?
You should just be able to do this directly - assuming that your arrays are of the same dimensions. For numpy arrays a and b:
np.sum(a != b)
a != b gives an array of Booleans (True when they are not equal element-wise and False when they are). Sum will give you the count of all elements that are not equal.
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.
New to python and need some help. I have a numpy array tuple with a shape of (1, 8760) with numbers within each of the 8760 locations. I've been trying to calculate if the values is between -2 and 2 then my new variable will be 0 else just keep the same value in the new variable. Here is what I tried and many others but I probably don't understand the array concept fully.
for x in flow:
if 2 > x < -2:
lflow = 0
else:
lflow = flow
I get this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
From what I read those functions gives me a true or false but I want to calculate of value instead of telling me if it matches or not. Please help.
Thanks
If your shape is (1,8760) an array of 8760 elements is assigned to x in your iteration, because the loop iterates the first axis containing one element of size 8760.
Furthermore I'd suggest to use "where" function instead of a loop:
# create a random array with 100 values in the range [-5,5]
a = numpy.random.random(100)*10 - 5
# return an array with all elements within that range set to 0
print numpy.where((a < -2) | (a > 2), a, 0)
Numpy uses boolean masks to select or assign values to arrays in bulk. For example, given the array
A = np.array([-3,-1,-2,0,1,5,2])
This mask represents all the values in A that are less than -2 or greater than 2
mask = (A < -2) | (A > 2)
Then use it to assign those values to 0
A[mask] = 0
This is much faster than using a regular loop in python, since numpy will perform this operation in c or fortran code