简体   繁体   中英

Fill NaN values based on operators from another column

I have a database (pd.DataFrame) like this:

    condition     odometer
0    new           NaN
1    bad           1100
2    excellent     110
3    NaN           200
4    NaN           2000
5    new           20
6    bad           NaN

And I want to fill the NaN of "condition" based on the values of "odometer":

new: odometer >0 and <= 100 
excellent: odometer >100 and <= 1000
bad: odometer >1000

I tried to do this but it is not working:

for i in range(len(database)): 
   if math.isnan(database['condition'][i]) == True:
      odometer = database['odometer'][i] 
      if   odometer > 0 & odometer <= 100:       value = 'new'
      elif odometer > 100 & odometer <= 1000:    value = 'excellent'
      elif odometer > 1000:                      value = 'bad'
      database['condition'][i] = value

Tried also making the first "if" condition:

database['condition'][i] == np.nan

But it doesn't work as well.

You can use DataFrame.apply() to generate a new condition column with your function, and replace it afterwards. Not sure what types your columns are. df['condition'].dtype will tell you. It looks like condition could either be string or object, which could create a bug in your logic. If it's a string column, you'll need to do a direct comparison == 'NaN'. If it's an object, you can use np.nan or math.nan. I included a sample database for each case below. You also might want to test the type of your odometer column.

import numpy as np
import pandas as pd

# condition column as string
df = pd.DataFrame({'condition':['new','bad','excellent','NaN','NaN','new','bad'], 'odometer':np.array([np.nan, 1100, 110, 200, 2000, 20, np.nan], dtype=object)})
# condition column as object
# df = pd.DataFrame({'condition':np.array(['new','bad','excellent',np.nan,np.nan,'new','bad'], dtype=object), 'odometer':np.array([np.nan, 1100, 110, 200, 2000, 20, np.nan], dtype=object)})
def f(database):
    if database['condition'] == 'NaN':
    #if np.isnan(database['condition']):
        odometer = database['odometer'] 
        if   odometer > 0 & odometer <= 100:       value = 'new'
        elif odometer > 100 & odometer <= 1000:    value = 'excellent'
        elif odometer > 1000:                      value = 'bad'
        return value
    return database['condition']

df['condition'] = df.apply(f, axis=1)

I have a nice one liner solution for you:

Lets create a sample dataframe:

import pandas as pd

df = pd.DataFrame({'condition':['new','bad',None,None,None], 'odometer':[None,1100,50,500,2000]})
df
Out:    
  condition odometer
0   new     NaN
1   bad     1100.0
2   None    50.0
3   None    500.0
4   None    2000.0

Solution:

df.condition = df.condition.fillna(df.odometer.apply(lambda number: 'new' if number in range(101) else 'excellent' if number in range(101,1000) else 'bad'))
df
Out:    
  condition  odometer
0       new        NaN
1       bad     1100.0
2       new       50.0
3 excellent      500.0
4       bad     2000.0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM