Table of Contents

get first element of series if not empty

tags | apply iloc[0] on a series only if it is not empty, pandas check for emptiness before applying iloc, check for emptiness before getting the first element, pandas iloc on empty series, pandas series return first value if not empty

Task

dataframe → filter rows → take one column → get the first value

Issue

We can't use something like

df.loc[mask]['C'].iloc[0]

since iloc[0] will throw

IndexError: single positional indexer is out-of-bounds

exception if df.loc[mask] is empty.

For example

% ipython
Python 3.8.5 (default, Sep  4 2020, 07:30:14) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.18.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: 
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8) + 1.5, 'D': np.arange(8) * 2})
print(df)

     A      B    C   D
0  foo    one  1.5   0
1  bar    one  2.5   2
2  foo    two  3.5   4
3  bar  three  4.5   6
4  foo    two  5.5   8
5  bar    two  6.5  10
6  foo    one  7.5  12
7  foo  three  8.5  14
In [2]:
mask = (df['A'] == 'foo') & (df['B'] == 'four')
df.loc[mask]['C'].iloc[0]

...
IndexError: single positional indexer is out-of-bounds

Solution

Use

next(iter(df.loc[mask]['C']), None)

or next(iter(series), default) in general.

With the above example

In [3]: 
next(iter(df.loc[mask]['C']), None)

In [4]: 
next(iter(df.loc[mask]['C']), None) is None
Out[4]: 
True

when df.loc[mask] is not empty, it works as expected.

In [5]: 
mask2 = (df['A'] == 'foo') & (df['B'] == 'two')
df.loc[mask2]['C']
Out[5]: 
2    3.5
4    5.5
Name: C, dtype: float64

In [6]: 
next(iter(df.loc[mask2]['C']), None)
Out[6]: 
3.5

In [7]: 
type(next(iter(df.loc[mask2]['C']), None))
Out[7]: 
float