Relational Operators with Pandas Series

Let's find out why the puzzle gives a ValueError and how we can fix it.

We'll cover the following

Try it yourself

Try executing the code below to see the result.

Press + to interact
import pandas as pd
def relu(n):
if n < 0:
return 0
return n
arr = pd.Series([-1, 0, 1])
print(relu(arr))

Explanation

The problematic line is if n < 0:. Here n is the result of arr < 0, which is a pandas.Series.

In [1]: import pandas as pd
In [2]: arr = pd.Series([-1, 0, 1])
In [3]: arr < 0
Out[3]:
0 True
1 False
2 False
dtype: bool

Once arr < 0 is computed, we use it in an if statement because of how Boolean values work in Python. Every Python object, not just True and False, has a Boolean value.

We can test the truth value of a Python object using the built-in bool function. In Python, everything is True except the following:

  • 00 numbers like 00, 0.00.0 and 0+0j0+0j.
  • Empty collections like [], {} and ''.
  • None
  • False

In addition, any object can state its own Boolean value using the __bool__ special method. The Boolean logic for pandas.Series is different from the logic of a list or a tuple because it raises an exception.

In [4]: bool(arr < 0)
...
ValueError: The truth value of a Series is ambiguous.
Use a.empty, a.bool(), a.item(), a.any() or a.all().

The exception tells us the reasoning. It follows the principles outlined in "The Zen of Python"A list of 19 golden principles of the best pythonic style of programming., which states, “In the face of ambiguity, refuse the temptation to guess.”

So, what are our options? We can use all() or any() but then we’ll need to check the type of n to see if it’s a plain number in a pandas.Series.

A function that works on a scalar, pandas.Series and a NumPy array is called a ufunc(), which is short for universal function.

Note: Most of the functions from NumPy or Pandas, such as min() or to_datetime(), are universal functions (ufunc()).

NumPy has a @vectorize decorator for converting scalar function to ufunc().

Solution

Press + to interact
import numpy as np
import pandas as pd
@np.vectorize
def relu(n):
if n < 0:
return 0
return n
arr = pd.Series([-1, 0, 1])
print(relu(arr))

Now, relu will work both on scalars (like 7,2.187, 2.18, and others) as well as vectors (like NumPy array and pandas.Series).

⚠️ Hint

Pay attention to types. The output of relu(n) is of type numpy.ndarray, not pandas.Series.

Get hands-on with 1300+ tech skills courses.