Unicode elementwise string comparison in numpy - python

I had a question about equality comparison with numpy and arrays of strings.
Say I define the following array:
x = np.array(['yes', 'no', 'maybe'])
Then I can test for equality with other strings and it does element wise comparison with the single string (following, I think, the broadcasting rules here: http://docs.scipy.org/doc/numpy-1.10.1/user/basics.broadcasting.html ?):
'yes' == x
#op : array([ True, False, False], dtype=bool)
x == 'yes'
#op : array([ True, False, False], dtype=bool)
However, if I compare with unicode strings I get different behaviour with element wise comparison only happening if I compare the array to the string and only a single comparison being made if I compare the string to the array.
x == u'yes'
#op : array([ True, False, False], dtype=bool)
u'yes' == x
#op : False
I can't find details of this behaviour in the numpy docs and was hoping someone could explain or point me to details of why comparison with unicode strings behaves differently?

The relevant piece of information is this part of the Python's coercion rules:
For objects xand y, first x.__op__(y) is tried. If this is not implemented or returns NotImplemented, y.__rop__(x) is tried.
Using your numpy array x, when the left-hand side is a str ('yes' == x):
'yes'.__eq__(x) returns NotImplemented and
therefore resolves to x.__eq__('yes') – resulting in numpy's element-wise comparison.
However, when the left-hand side is a unicode (u'yes' == x):
u'yes'.__eq__(x) simply returns False.
The reason for the different __eq__ behaviours is that str.__eq__() simply returns NotImplemented if its argument is not a str type, whereas unicode.__eq__() first tries to convert its argument to a unicode, and only returns NotImplemented if that conversion fails. In this case, the numpy array is convertible to a unicode: u'yes' == x is essentially u'yes' == unicode(x).

Related

Loop in pandas dataframe stopping after two three iterations [duplicate]

What explains the difference in behavior of boolean and bitwise operations on lists vs NumPy arrays?
I'm confused about the appropriate use of & vs and in Python, illustrated in the following examples.
mylist1 = [True, True, True, False, True]
mylist2 = [False, True, False, True, False]
>>> len(mylist1) == len(mylist2)
True
# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]
# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?
>>> import numpy as np
# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?
# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False, True, False, False, False], dtype=bool)
# This is the output I was expecting!
This answer and this answer helped me understand that and is a boolean operation but & is a bitwise operation.
I read about bitwise operations to better understand the concept, but I am struggling to use that information to make sense of my above 4 examples.
Example 4 led me to my desired output, so that is fine, but I am still confused about when/how/why I should use and vs &. Why do lists and NumPy arrays behave differently with these operators?
Can anyone help me understand the difference between boolean and bitwise operations to explain why they handle lists and NumPy arrays differently?
and tests whether both expressions are logically True while & (when used with True/False values) tests if both are True.
In Python, empty built-in objects are typically treated as logically False while non-empty built-ins are logically True. This facilitates the common use case where you want to do something if a list is empty and something else if the list is not. Note that this means that the list [False] is logically True:
>>> if [False]:
... print 'True'
...
True
So in Example 1, the first list is non-empty and therefore logically True, so the truth value of the and is the same as that of the second list. (In our case, the second list is non-empty and therefore logically True, but identifying that would require an unnecessary step of calculation.)
For example 2, lists cannot meaningfully be combined in a bitwise fashion because they can contain arbitrary unlike elements. Things that can be combined bitwise include: Trues and Falses, integers.
NumPy objects, by contrast, support vectorized calculations. That is, they let you perform the same operations on multiple pieces of data.
Example 3 fails because NumPy arrays (of length > 1) have no truth value as this prevents vector-based logic confusion.
Example 4 is simply a vectorized bit and operation.
Bottom Line
If you are not dealing with arrays and are not performing math manipulations of integers, you probably want and.
If you have vectors of truth values that you wish to combine, use numpy with &.
About list
First a very important point, from which everything will follow (I hope).
In ordinary Python, list is not special in any way (except having cute syntax for constructing, which is mostly a historical accident). Once a list [3,2,6] is made, it is for all intents and purposes just an ordinary Python object, like a number 3, set {3,7}, or a function lambda x: x+5.
(Yes, it supports changing its elements, and it supports iteration, and many other things, but that's just what a type is: it supports some operations, while not supporting some others. int supports raising to a power, but that doesn't make it very special - it's just what an int is. lambda supports calling, but that doesn't make it very special - that's what lambda is for, after all:).
About and
and is not an operator (you can call it "operator", but you can call "for" an operator too:). Operators in Python are (implemented through) methods called on objects of some type, usually written as part of that type. There is no way for a method to hold an evaluation of some of its operands, but and can (and must) do that.
The consequence of that is that and cannot be overloaded, just like for cannot be overloaded. It is completely general, and communicates through a specified protocol. What you can do is customize your part of the protocol, but that doesn't mean you can alter the behavior of and completely. The protocol is:
Imagine Python interpreting "a and b" (this doesn't happen literally this way, but it helps understanding). When it comes to "and", it looks at the object it has just evaluated (a), and asks it: are you true? (NOT: are you True?) If you are an author of a's class, you can customize this answer. If a answers "no", and (skips b completely, it is not evaluated at all, and) says: a is my result (NOT: False is my result).
If a doesn't answer, and asks it: what is your length? (Again, you can customize this as an author of a's class). If a answers 0, and does the same as above - considers it false (NOT False), skips b, and gives a as result.
If a answers something other than 0 to the second question ("what is your length"), or it doesn't answer at all, or it answers "yes" to the first one ("are you true"), and evaluates b, and says: b is my result. Note that it does NOT ask b any questions.
The other way to say all of this is that a and b is almost the same as b if a else a, except a is evaluated only once.
Now sit for a few minutes with a pen and paper, and convince yourself that when {a,b} is a subset of {True,False}, it works exactly as you would expect of Boolean operators. But I hope I have convinced you it is much more general, and as you'll see, much more useful this way.
Putting those two together
Now I hope you understand your example 1. and doesn't care if mylist1 is a number, list, lambda or an object of a class Argmhbl. It just cares about mylist1's answer to the questions of the protocol. And of course, mylist1 answers 5 to the question about length, so and returns mylist2. And that's it. It has nothing to do with elements of mylist1 and mylist2 - they don't enter the picture anywhere.
Second example: & on list
On the other hand, & is an operator like any other, like + for example. It can be defined for a type by defining a special method on that class. int defines it as bitwise "and", and bool defines it as logical "and", but that's just one option: for example, sets and some other objects like dict keys views define it as a set intersection. list just doesn't define it, probably because Guido didn't think of any obvious way of defining it.
numpy
On the other leg:-D, numpy arrays are special, or at least they are trying to be. Of course, numpy.array is just a class, it cannot override and in any way, so it does the next best thing: when asked "are you true", numpy.array raises a ValueError, effectively saying "please rephrase the question, my view of truth doesn't fit into your model". (Note that the ValueError message doesn't speak about and - because numpy.array doesn't know who is asking it the question; it just speaks about truth.)
For &, it's completely different story. numpy.array can define it as it wishes, and it defines & consistently with other operators: pointwise. So you finally get what you want.
HTH,
The short-circuiting boolean operators (and, or) can't be overriden because there is no satisfying way to do this without introducing new language features or sacrificing short circuiting. As you may or may not know, they evaluate the first operand for its truth value, and depending on that value, either evaluate and return the second argument, or don't evaluate the second argument and return the first:
something_true and x -> x
something_false and x -> something_false
something_true or x -> something_true
something_false or x -> x
Note that the (result of evaluating the) actual operand is returned, not truth value thereof.
The only way to customize their behavior is to override __nonzero__ (renamed to __bool__ in Python 3), so you can affect which operand gets returned, but not return something different. Lists (and other collections) are defined to be "truthy" when they contain anything at all, and "falsey" when they are empty.
NumPy arrays reject that notion: For the use cases they aim at, two different notions of truth are common: (1) Whether any element is true, and (2) whether all elements are true. Since these two are completely (and silently) incompatible, and neither is clearly more correct or more common, NumPy refuses to guess and requires you to explicitly use .any() or .all().
& and | (and not, by the way) can be fully overriden, as they don't short circuit. They can return anything at all when overriden, and NumPy makes good use of that to do element-wise operations, as they do with practically any other scalar operation. Lists, on the other hand, don't broadcast operations across their elements. Just as mylist1 - mylist2 doesn't mean anything and mylist1 + mylist2 means something completely different, there is no & operator for lists.
Example 1:
This is how the and operator works.
x and y =>
if x is false, then x, else y
So in other words, since mylist1 is not False, the result of the expression is mylist2. (Only empty lists evaluate to False.)
Example 2:
The & operator is for a bitwise and, as you mention. Bitwise operations only work on numbers. The result of a & b is a number composed of 1s in bits that are 1 in both a and b. For example:
>>> 3 & 1
1
It's easier to see what's happening using a binary literal (same numbers as above):
>>> 0b0011 & 0b0001
0b0001
Bitwise operations are similar in concept to boolean (truth) operations, but they work only on bits.
So, given a couple statements about my car
My car is red
My car has wheels
The logical "and" of these two statements is:
(is my car red?) and (does car have wheels?) => logical true of false value
Both of which are true, for my car at least. So the value of the statement as a whole is logically true.
The bitwise "and" of these two statements is a little more nebulous:
(the numeric value of the statement 'my car is red') & (the numeric value of the statement 'my car has wheels') => number
If python knows how to convert the statements to numeric values, then it will do so and compute the bitwise-and of the two values. This may lead you to believe that & is interchangeable with and, but as with the above example they are different things. Also, for the objects that can't be converted, you'll just get a TypeError.
Example 3 and 4:
Numpy implements arithmetic operations for arrays:
Arithmetic and comparison operations on ndarrays are defined as element-wise operations, and generally yield ndarray objects as results.
But does not implement logical operations for arrays, because you can't overload logical operators in python. That's why example three doesn't work, but example four does.
So to answer your and vs & question: Use and.
The bitwise operations are used for examining the structure of a number (which bits are set, which bits aren't set). This kind of information is mostly used in low-level operating system interfaces (unix permission bits, for example). Most python programs won't need to know that.
The logical operations (and, or, not), however, are used all the time.
In Python an expression of X and Y returns Y, given that bool(X) == True or any of X or Y evaluate to False, e.g.:
True and 20
>>> 20
False and 20
>>> False
20 and []
>>> []
Bitwise operator is simply not defined for lists. But it is defined for integers - operating over the binary representation of the numbers. Consider 16 (01000) and 31 (11111):
16 & 31
>>> 16
NumPy is not a psychic, it does not know, whether you mean that
e.g. [False, False] should be equal to True in a logical expression. In this it overrides a standard Python behaviour, which is: "Any empty collection with len(collection) == 0 is False".
Probably an expected behaviour of NumPy's arrays's & operator.
For the first example and base on the django's doc
It will always return the second list, indeed a non empty list is see as a True value for Python thus python return the 'last' True value so the second list
In [74]: mylist1 = [False]
In [75]: mylist2 = [False, True, False, True, False]
In [76]: mylist1 and mylist2
Out[76]: [False, True, False, True, False]
In [77]: mylist2 and mylist1
Out[77]: [False]
Operations with a Python list operate on the list. list1 and list2 will check if list1 is empty, and return list1 if it is, and list2 if it isn't. list1 + list2 will append list2 to list1, so you get a new list with len(list1) + len(list2) elements.
Operators that only make sense when applied element-wise, such as &, raise a TypeError, as element-wise operations aren't supported without looping through the elements.
Numpy arrays support element-wise operations. array1 & array2 will calculate the bitwise or for each corresponding element in array1 and array2. array1 + array2 will calculate the sum for each corresponding element in array1 and array2.
This does not work for and and or.
array1 and array2 is essentially a short-hand for the following code:
if bool(array1):
return array2
else:
return array1
For this you need a good definition of bool(array1). For global operations like used on Python lists, the definition is that bool(list) == True if list is not empty, and False if it is empty. For numpy's element-wise operations, there is some disambiguity whether to check if any element evaluates to True, or all elements evaluate to True. Because both are arguably correct, numpy doesn't guess and raises a ValueError when bool() is (indirectly) called on an array.
Good question. Similar to the observation you have about examples 1 and 4 (or should I say 1 & 4 :) ) over logical and bitwise & operators, I experienced on sum operator. The numpy sum and py sum behave differently as well. For example:
Suppose "mat" is a numpy 5x5 2d array such as:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
Then numpy.sum(mat) gives total sum of the entire matrix. Whereas the built-in sum from Python such as sum(mat) totals along the axis only. See below:
np.sum(mat) ## --> gives 325
sum(mat) ## --> gives array([55, 60, 65, 70, 75])

Pandas order of operation in & and | conditionals in short circuit evaluation [duplicate]

What explains the difference in behavior of boolean and bitwise operations on lists vs NumPy arrays?
I'm confused about the appropriate use of & vs and in Python, illustrated in the following examples.
mylist1 = [True, True, True, False, True]
mylist2 = [False, True, False, True, False]
>>> len(mylist1) == len(mylist2)
True
# ---- Example 1 ----
>>> mylist1 and mylist2
[False, True, False, True, False]
# I would have expected [False, True, False, False, False]
# ---- Example 2 ----
>>> mylist1 & mylist2
TypeError: unsupported operand type(s) for &: 'list' and 'list'
# Why not just like example 1?
>>> import numpy as np
# ---- Example 3 ----
>>> np.array(mylist1) and np.array(mylist2)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# Why not just like Example 4?
# ---- Example 4 ----
>>> np.array(mylist1) & np.array(mylist2)
array([False, True, False, False, False], dtype=bool)
# This is the output I was expecting!
This answer and this answer helped me understand that and is a boolean operation but & is a bitwise operation.
I read about bitwise operations to better understand the concept, but I am struggling to use that information to make sense of my above 4 examples.
Example 4 led me to my desired output, so that is fine, but I am still confused about when/how/why I should use and vs &. Why do lists and NumPy arrays behave differently with these operators?
Can anyone help me understand the difference between boolean and bitwise operations to explain why they handle lists and NumPy arrays differently?
and tests whether both expressions are logically True while & (when used with True/False values) tests if both are True.
In Python, empty built-in objects are typically treated as logically False while non-empty built-ins are logically True. This facilitates the common use case where you want to do something if a list is empty and something else if the list is not. Note that this means that the list [False] is logically True:
>>> if [False]:
... print 'True'
...
True
So in Example 1, the first list is non-empty and therefore logically True, so the truth value of the and is the same as that of the second list. (In our case, the second list is non-empty and therefore logically True, but identifying that would require an unnecessary step of calculation.)
For example 2, lists cannot meaningfully be combined in a bitwise fashion because they can contain arbitrary unlike elements. Things that can be combined bitwise include: Trues and Falses, integers.
NumPy objects, by contrast, support vectorized calculations. That is, they let you perform the same operations on multiple pieces of data.
Example 3 fails because NumPy arrays (of length > 1) have no truth value as this prevents vector-based logic confusion.
Example 4 is simply a vectorized bit and operation.
Bottom Line
If you are not dealing with arrays and are not performing math manipulations of integers, you probably want and.
If you have vectors of truth values that you wish to combine, use numpy with &.
About list
First a very important point, from which everything will follow (I hope).
In ordinary Python, list is not special in any way (except having cute syntax for constructing, which is mostly a historical accident). Once a list [3,2,6] is made, it is for all intents and purposes just an ordinary Python object, like a number 3, set {3,7}, or a function lambda x: x+5.
(Yes, it supports changing its elements, and it supports iteration, and many other things, but that's just what a type is: it supports some operations, while not supporting some others. int supports raising to a power, but that doesn't make it very special - it's just what an int is. lambda supports calling, but that doesn't make it very special - that's what lambda is for, after all:).
About and
and is not an operator (you can call it "operator", but you can call "for" an operator too:). Operators in Python are (implemented through) methods called on objects of some type, usually written as part of that type. There is no way for a method to hold an evaluation of some of its operands, but and can (and must) do that.
The consequence of that is that and cannot be overloaded, just like for cannot be overloaded. It is completely general, and communicates through a specified protocol. What you can do is customize your part of the protocol, but that doesn't mean you can alter the behavior of and completely. The protocol is:
Imagine Python interpreting "a and b" (this doesn't happen literally this way, but it helps understanding). When it comes to "and", it looks at the object it has just evaluated (a), and asks it: are you true? (NOT: are you True?) If you are an author of a's class, you can customize this answer. If a answers "no", and (skips b completely, it is not evaluated at all, and) says: a is my result (NOT: False is my result).
If a doesn't answer, and asks it: what is your length? (Again, you can customize this as an author of a's class). If a answers 0, and does the same as above - considers it false (NOT False), skips b, and gives a as result.
If a answers something other than 0 to the second question ("what is your length"), or it doesn't answer at all, or it answers "yes" to the first one ("are you true"), and evaluates b, and says: b is my result. Note that it does NOT ask b any questions.
The other way to say all of this is that a and b is almost the same as b if a else a, except a is evaluated only once.
Now sit for a few minutes with a pen and paper, and convince yourself that when {a,b} is a subset of {True,False}, it works exactly as you would expect of Boolean operators. But I hope I have convinced you it is much more general, and as you'll see, much more useful this way.
Putting those two together
Now I hope you understand your example 1. and doesn't care if mylist1 is a number, list, lambda or an object of a class Argmhbl. It just cares about mylist1's answer to the questions of the protocol. And of course, mylist1 answers 5 to the question about length, so and returns mylist2. And that's it. It has nothing to do with elements of mylist1 and mylist2 - they don't enter the picture anywhere.
Second example: & on list
On the other hand, & is an operator like any other, like + for example. It can be defined for a type by defining a special method on that class. int defines it as bitwise "and", and bool defines it as logical "and", but that's just one option: for example, sets and some other objects like dict keys views define it as a set intersection. list just doesn't define it, probably because Guido didn't think of any obvious way of defining it.
numpy
On the other leg:-D, numpy arrays are special, or at least they are trying to be. Of course, numpy.array is just a class, it cannot override and in any way, so it does the next best thing: when asked "are you true", numpy.array raises a ValueError, effectively saying "please rephrase the question, my view of truth doesn't fit into your model". (Note that the ValueError message doesn't speak about and - because numpy.array doesn't know who is asking it the question; it just speaks about truth.)
For &, it's completely different story. numpy.array can define it as it wishes, and it defines & consistently with other operators: pointwise. So you finally get what you want.
HTH,
The short-circuiting boolean operators (and, or) can't be overriden because there is no satisfying way to do this without introducing new language features or sacrificing short circuiting. As you may or may not know, they evaluate the first operand for its truth value, and depending on that value, either evaluate and return the second argument, or don't evaluate the second argument and return the first:
something_true and x -> x
something_false and x -> something_false
something_true or x -> something_true
something_false or x -> x
Note that the (result of evaluating the) actual operand is returned, not truth value thereof.
The only way to customize their behavior is to override __nonzero__ (renamed to __bool__ in Python 3), so you can affect which operand gets returned, but not return something different. Lists (and other collections) are defined to be "truthy" when they contain anything at all, and "falsey" when they are empty.
NumPy arrays reject that notion: For the use cases they aim at, two different notions of truth are common: (1) Whether any element is true, and (2) whether all elements are true. Since these two are completely (and silently) incompatible, and neither is clearly more correct or more common, NumPy refuses to guess and requires you to explicitly use .any() or .all().
& and | (and not, by the way) can be fully overriden, as they don't short circuit. They can return anything at all when overriden, and NumPy makes good use of that to do element-wise operations, as they do with practically any other scalar operation. Lists, on the other hand, don't broadcast operations across their elements. Just as mylist1 - mylist2 doesn't mean anything and mylist1 + mylist2 means something completely different, there is no & operator for lists.
Example 1:
This is how the and operator works.
x and y =>
if x is false, then x, else y
So in other words, since mylist1 is not False, the result of the expression is mylist2. (Only empty lists evaluate to False.)
Example 2:
The & operator is for a bitwise and, as you mention. Bitwise operations only work on numbers. The result of a & b is a number composed of 1s in bits that are 1 in both a and b. For example:
>>> 3 & 1
1
It's easier to see what's happening using a binary literal (same numbers as above):
>>> 0b0011 & 0b0001
0b0001
Bitwise operations are similar in concept to boolean (truth) operations, but they work only on bits.
So, given a couple statements about my car
My car is red
My car has wheels
The logical "and" of these two statements is:
(is my car red?) and (does car have wheels?) => logical true of false value
Both of which are true, for my car at least. So the value of the statement as a whole is logically true.
The bitwise "and" of these two statements is a little more nebulous:
(the numeric value of the statement 'my car is red') & (the numeric value of the statement 'my car has wheels') => number
If python knows how to convert the statements to numeric values, then it will do so and compute the bitwise-and of the two values. This may lead you to believe that & is interchangeable with and, but as with the above example they are different things. Also, for the objects that can't be converted, you'll just get a TypeError.
Example 3 and 4:
Numpy implements arithmetic operations for arrays:
Arithmetic and comparison operations on ndarrays are defined as element-wise operations, and generally yield ndarray objects as results.
But does not implement logical operations for arrays, because you can't overload logical operators in python. That's why example three doesn't work, but example four does.
So to answer your and vs & question: Use and.
The bitwise operations are used for examining the structure of a number (which bits are set, which bits aren't set). This kind of information is mostly used in low-level operating system interfaces (unix permission bits, for example). Most python programs won't need to know that.
The logical operations (and, or, not), however, are used all the time.
In Python an expression of X and Y returns Y, given that bool(X) == True or any of X or Y evaluate to False, e.g.:
True and 20
>>> 20
False and 20
>>> False
20 and []
>>> []
Bitwise operator is simply not defined for lists. But it is defined for integers - operating over the binary representation of the numbers. Consider 16 (01000) and 31 (11111):
16 & 31
>>> 16
NumPy is not a psychic, it does not know, whether you mean that
e.g. [False, False] should be equal to True in a logical expression. In this it overrides a standard Python behaviour, which is: "Any empty collection with len(collection) == 0 is False".
Probably an expected behaviour of NumPy's arrays's & operator.
For the first example and base on the django's doc
It will always return the second list, indeed a non empty list is see as a True value for Python thus python return the 'last' True value so the second list
In [74]: mylist1 = [False]
In [75]: mylist2 = [False, True, False, True, False]
In [76]: mylist1 and mylist2
Out[76]: [False, True, False, True, False]
In [77]: mylist2 and mylist1
Out[77]: [False]
Operations with a Python list operate on the list. list1 and list2 will check if list1 is empty, and return list1 if it is, and list2 if it isn't. list1 + list2 will append list2 to list1, so you get a new list with len(list1) + len(list2) elements.
Operators that only make sense when applied element-wise, such as &, raise a TypeError, as element-wise operations aren't supported without looping through the elements.
Numpy arrays support element-wise operations. array1 & array2 will calculate the bitwise or for each corresponding element in array1 and array2. array1 + array2 will calculate the sum for each corresponding element in array1 and array2.
This does not work for and and or.
array1 and array2 is essentially a short-hand for the following code:
if bool(array1):
return array2
else:
return array1
For this you need a good definition of bool(array1). For global operations like used on Python lists, the definition is that bool(list) == True if list is not empty, and False if it is empty. For numpy's element-wise operations, there is some disambiguity whether to check if any element evaluates to True, or all elements evaluate to True. Because both are arguably correct, numpy doesn't guess and raises a ValueError when bool() is (indirectly) called on an array.
Good question. Similar to the observation you have about examples 1 and 4 (or should I say 1 & 4 :) ) over logical and bitwise & operators, I experienced on sum operator. The numpy sum and py sum behave differently as well. For example:
Suppose "mat" is a numpy 5x5 2d array such as:
array([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
Then numpy.sum(mat) gives total sum of the entire matrix. Whereas the built-in sum from Python such as sum(mat) totals along the axis only. See below:
np.sum(mat) ## --> gives 325
sum(mat) ## --> gives array([55, 60, 65, 70, 75])

Python what does > sign

I recently found this part of code:
filteredImage = image > filters.threshold_otsu(image)
In most languages image > filters.threshold_otsu(image) would return true or false. In this case filteredImage is ndarray. So what exactly happens in this code?
Python allows operator overloading. So you'd best consult the documentation for your particular use case - here its a boolean mask as the comments have pointed out, but python allows you to use any operator to do almost anything you like.
For example, you could have a class that uses > to decide if one array is longer than another array if you implemented your own array class. The best thing to do would be to search the documentation for your particular use case and look for operators.
Further Clarification
Imagine I made a class called train, that just holds a string, and I wanted to use > to stick two trains together. (looks like it would be nice to do that :P)
class Train:
def __init__(self, cargo):
self.cargo = cargo
def __call__(self):
print("__{0}__".format(self.cargo))
def __gt__(self, another):
self.cargo = "{0}__{1}".format(self.cargo, another.cargo)
# Make two trains
a = Train("check")
b = Train("me")
a()
b()
# Join the trains and print again
a > b
a()
b()
Which would output
__check__
__me__
__check__me__
__me__
Notice that I didn't use this to return true or false, and I didn't even make the operator return anything. It would be important for me to document this in any documentation I provide to tell you what my intended use case for the > symbol is for my class.
This is a hugely useful feature that gets used all the time (eg multiplication in the numpy library - python can't natively multiply numpy.arrays).
Since you point out its an ndarray, numpy uses vectorized implementation of element wise comparision and returns a boolean mask which will also be a numpy array. An example :
a = np.array([1,2,7,8,9])
b = np.array([1,2,3,4,5])
a <= b
array([ True, True, False, False, False], dtype=bool)
Which is almost equivalent to below if done using for loop for 1D array :
k = []
for i,j in zip(a,b):
k.append(i<=j)
k = np.array(k)
array([ True, True, False, False, False], dtype=bool)
Numpy support almost all operators. For more info and logic function you can check Documentation

numpy.where() function throws a FutureWarning, returns scalar instead of list

I am currently working with NumPy version 1.12.1, and every call to numpy.where() returns an empty list with the following warning:
FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
I am comparing a string, date_now and a list, dates_list:
np.where(date_now==dates_list)
This causes errors, as the program subsequently calls functions that expect the numpy.where() output to be a non-empty. Does anyone have a solution for this?
Thanks in advance.
In your current comparison, you are comparing the entire list object, dates_list, to a string, date_now. This will cause element-wise comparison to fail and return a scalar as if you are just comparing two scalar values:
date_now = '2017-07-10'
dates_list = ['2017-07-10', '2017-07-09', '2017-07-08']
np.where(dates_list==date_now, True, False)
Out[3]: array(0)
What you want is to declare dates_list as a NumPy array to facilitate element-wise comparison.
np.where(np.array(dates_list)==date_now, True, False)
Out[8]: array([ True, False, False], dtype=bool)

How to find slice object in numpy array

I have a numpy array containing integers and slice objects, e.g.:
x = np.array([0,slice(None)])
How do I retrieve the (logical) indices of the integers or slice objects? I tried np.isfinite(x) (producing an error), np.isreal(x) (all True), np.isscalar(x) (not element-wise), all in vain.
What seems to work though is
ind = x<np.Inf # Out[1]: array([True, False], dtype=bool)
but I'm reluctant to use a numerical comparison on an object who's numerical value is completely arbitrary (and might change in the future?). Is there a better solution to achieve this?
You can do this:
import numpy as np
checker = np.vectorize( lambda x: isinstance(x,slice) )
x = np.array([0,slice(None),slice(None),0,0,slice(None)])
checker(x)
#array([False, True, True, False, False, True], dtype=bool)

Categories