Empty numpy array boolean contradiction [duplicate] - python

This question already has answers here:
How do Python's any and all functions work?
(10 answers)
Closed 4 years ago.
I accidentally found something in Numpy, which I can't really understand. If I check an empty Numpy array for any true value
np.array([]).any()
it will evaluate to false, whereas if I check all values to be true
np.array([]).all()
it evaluates to true. This appears weird to me since no value is true but at the same time all values are true...

This isn't a bug, it returns True because all values are not equal to zero which is the criteria for returning True see the following note:
Not a Number (NaN), positive infinity and negative infinity evaluate
to True because these are not equal to zero.
compare with the following:
In[102]:
np.array([True,]).all()
Out[102]: True
This would be equivalent to an array full of NaN which would return True

The logic you are seeing is not specific to NumPy. This is a Python convention which has been implemented in NumPy:
any returns True if any value is True. Otherwise False.
all returns True if no value is False. Otherwise True.
See the pseuedo-code in the docs to see the logic in pure Python.
In the case of np.array([]).any() or any([]), there are no True values, because you have a 0-dimensional array or a 0-length list. Therefore, the result is False.
In the case of np.array([]).all() or all([]), there are no False values, because you have a 0-dimensional array or a 0-length list. Therefore, the result is True.

This is a normal behavior.
It is not possible to find a value that is true, so np.array([]).any() is False
For every value in the array, this value is False (It is easy to check, because there are no values in the array, so you don't have to check anything).

Related

Why does [] and bool return []? [duplicate]

This question already has answers here:
and / or operators return value [duplicate]
(4 answers)
Closed 4 years ago.
I am trying to return a boolean in a function like this:
return mylist and any(condition(x) for x in mylist)
The behavior should be to return True if the list is empty or if any element in it meets the condition. I am using the first operand as a shortcircuit since any would return True if the list was empty, which is not what I am after.
I would expect [] and boolval to return False since the list is empty, but to my surprise it returns [] whether boolval is True or False. I would expect the first operand to be automatically evaluated as a boolean since it is involved in a comparison operation, and not whatever is happening.
I am not really asking how to solve my problem, which is easily done by an explicit type conversion: bool(mylist), but rather asking what is happening and why.
edit: when I ask "why" this is happening I am not looking for the "facts" only, as they are already explained in the linked duplicate question, but also the reasons behind the implementation of this behavior.
The and and or operators do not return True/False. They return the last thing evaluated (that's the case in other dynamic languages too, eg. javascript).
The official documentation describes that
for and, the first falsy value, or the last operand
for or, the first truthy value, or the last operand
That's by design, so you can create expressions like return username or 'guest'. So, if you want guarantee that a boolean value is returned, you have to
return bool(x or y)
instead of
return x or y
Because as khelwood said:
x and y gives x if x is falsey, otherwise it gives y.
That's the point, (and is not or :-)), so still best is:
return all([my_list,any(condition(x) for x in my_list)])
This has to do with how python evaluate the expression.
An empty list is considered as false by python, that means that the code after 'and' will not be executed, as this will not change the result.
Python does not need to convert the empty list into bool as it is not compared to anything, and just return it as empty list.
This shouldn't change anything for you, if you test the returned value of the function, it will be evaluate the same way as if the function did return False.

How to check if all values in a dataframe are True

pd.DataFrame.all and pd.DataFrame.any convert to bool all values and than assert all identities with the keyword True. This is ok as long as we are fine with the fact that non-empty lists and strings evaluate to True. However let assume that this is not the case.
>>> pd.DataFrame([True, 'a']).all().item()
True # Wrong
A workaround is to assert equality with True, but a comparison to True does not sound pythonic.
>>> (pd.DataFrame([True, 'a']) == True).all().item()
False # Right
Question: can we assert for identity with True without using == True
First of all, I do not advise this. Please do not use mixed dtypes inside your dataframe columns - that defeats the purpose of dataframes and they are no more useful than lists and no more performant than loops.
Now, addressing your actual question, spolier alert, you can't get over the ==. But you can hide it using the eq function. You may use
df.eq(True).all()
Or,
df.where(df.eq(True), False).all()
Note that
df.where(df.eq(True), False)
0
0 True
1 False
Which you may find useful if you want to convert non-"True" values to False for any other reason.
I would actually use
(pd.DataFrame([True, 'a']) == True).all().item()
This way, you're checking for the value of the object, not just checking the "truthy-ness" of it.
This seems perfectly pythonic to me because you're explicitly checking for the value of the object, not just whether or not it's a truthy value.

Using any() function for value of 1.5

I want to know if any of the values contained in a 1024 length array are greater than the value 1.2. I've found the median value of the array and its 1.1, so I know the array contains values that are higher and lower than 1. The code that I'm using is shown below and the resulting message i'm getting is "No signal present".
if in1_norm.any()>=1.2: ## Comparison of array to threshold. Using
## a generic value for now
print "A signal is present"
else:
print "No signal is present"
I've read in a previous post that any() evaluates as a value of 1 or "true, so, I believe I'm not getting the correct result because the comparison is viewed as 1>=1.2, which is false. Is there any other way of doing this??
Thanks
The part in1_norm.any()>=1.2 will not do what you're intended. The any() function returns True if any of the array's items can be evaluated as True otherwise it will return False. You need to first compare your items with 1.2 then call the any on the results.
(in1_norm >= 1.2).any()

Difference between if and if not python

Can anybody please tell me here what is the exact difference between if and if not here in the code.
def postordertraversse(self,top):
m=[]
if(top):
if not self.postordertraversse(top.left):
m.append(top.root)
top_most=m.pop(0)
conv=createlist();
conv.postordertraversse(conv.top)
What i can understand is if top means if top object instance exists then move inside the block and check if not i.e till top.left is not null keep appending.
if x: means "if x is truthy".
if not x: means "if x is falsey".
Whether something is truthy or falsey depends on what kind of object it is.
For numbers, 0 is falsey, and all other values are truthy.
For boolean values, True is truthy and False is falsey (obviously!)
For collections (lists, tuples, dictionaries, strings, etc), empty ones are falsey and non-empty ones are truthy.
So in your example code, the two if statements are saying:
if top is truthy:
if the result of self.postordertraversse(top.left) is falsey:
not in python is like negation in other programming languages.
'not' statement just converts further expression. For example:
not True - False
not False - True

Python without if and with if

>What's wrong with this..
Code-1
def first_last6(nums):
if nums[0]==6 or nums[len(nums)-1] == 6:
return True
else:
return False
Code-2
def first_last6(nums):
return (nums[0]==6 or nums[-1]== 6)
How come both True?
There seem to be two questions inside, so I’ll answer both.
First of all, why are nums[len(nums)-1] and nums[-1] the same? When specifying an index, Python allows you to use negative numbers that are interpreted like this: if i in nums[i] is negative, then the index len(nums)+i is returned. So, basically, [-1] will get the last element, [-2] the second to last etc.
The second question is why the two formats are identical:
if expression:
return True
else
return False
and
return expression
expression in this case is an expression that returns a boolean type, so either True or False. The if statements checks exactly that; if the expression equals to true, it will return true, otherwise (if the expression equals to false) it will return false.
So you can (and should, to make it cleaner) just return the expression itself, as it is already true or false.
In the case expression itself is not a boolean expression, the if statement will still check to what boolean type it would evaluate (for example a non-empty string would be true, or a number other than 0 would be true too). To keep the short syntax, you can then explicitely convert the expression to a boolean value, using bool(expression), as larsmans mentioned in the comments.
nums[-k] is a shorthand for nums[len(nums)-k]. To get the k-th last element you use the notation nums[-k]. Usually it is clear what the notation stands for and the compiler knows how to turn that python code into machine code, which is why certain language contructs are possible and others are not. Other short hands include nums[:k] to get the first k elements, nums[:-k] to get all elements up to the k-th last element etc. Via google, python docs, you will find much more on this. List operations are a great strength of the python.
http://www.diveintopython.net/native_data_types/lists.html
uh, because both are exactly the same and they both evaluate to True.

Categories

Resources