5

In using the iloc method for Pandas dataframe, I want to return zero if the value does not exist: (I have a query which it will always return either one row or an empty dataframe. I want the first left value when it exists)

import pandas as pd

mydict = {"col1":[1,2], "price":[1000,2000]}
df = pd.DataFrame(mydict)
query=df[df['price']>3000]

try:
    print(query.iloc[0][0])
except BaseException:
    print(0)

#print result: 0

Is there any better way or built-in method for iloc? I am thinking of something similar to the get method of Python dictionaries!

3
  • Chain a .fillna(0) to the end of your query or data frame and this will handle nas for you. Commented Jan 23, 2019 at 20:01
  • Why don't you use fillna to replace missing values with 0? Commented Jan 23, 2019 at 20:01
  • 1
    fillna(0) will never work, this is about what happens when query is an empty dataframe. Filling null in an empty dataframe with 0 will have no impact. Commented Jan 23, 2019 at 20:10

3 Answers 3

7

You can be more pythonic replacing your try/except block with:

print(0 if len(query)==0 else query.iloc[0][0])

Explanation: len() applied to a pandas Dataframe returns the number of rows.

Update: as suggested in comments, query.empty this is more idiomatic and .iat is better for scalar lookups, hence:

print(0 if query.empty else query.iat[0,0])

Sign up to request clarification or add additional context in comments.

2 Comments

nice! that's what I wanted! a simple len would help here! Combining the two answers I would suggest!: print(query.iat[0,0] if len(query)!=0 else 0)
More idiomatic is to use if not query.empty instead of if len(query) == 0
3

You can use something like

next(iter(series), default)

For example, using your input

In [1]: 
import pandas as pd
mydict = {"col1":[1,2], "price":[1000,2000]}
df = pd.DataFrame(mydict)
df
Out[1]: 
   col1  price
0     1   1000
1     2   2000

and filtering on price > 2000, gives the default value (which we are setting to zero) since df.loc[mask] would be empty

In [2]: 
mask = (df['price']>2000)
next(iter(df.loc[mask]['col1']), 0)
Out[2]: 
0

The other cases work as expected. For example, filtering on price > 1500, gives 2

In [3]: 
mask = (df['price']>1500)
next(iter(df.loc[mask]['col1']), 0)
Out[3]: 
2

and filtering on price > 500 gives 1

In [4]: 
mask = (df['price']>500)
next(iter(df.loc[mask]['col1']), 0)
Out[4]: 
1

1 Comment

Extremely clever and concise way of solving this problem. Thank you
0

There's no intrinsically better way than try / except. The rationale for iloc is indexing by integer positional location.

The behaviour and functionality is consistent with NumPy np.ndarray, Python list and other indexable objects. There's no direct way to index either the first value of a list or return 0 if the list is empty.

A slightly better way is to be explicit and catch IndexError only and use iat for accessing scalars by integer location. Moreover, you can index by row and column simultaneously:

try:
    print(query.iat[0, 0])
except IndexError:
    print(0)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.