Hugo
Hugo

Reputation: 1688

How do I apply a function to a pandas dataframe?

I have tried to apply a function to a pandas dataframe like this

fogo = intervalo.resample('D', how = ['max']).TMP
fogo['Tmin'] = intervalo.resample('D', how = ['min']).TMP
fogo['Rain'] = intervalo.resample('D', how = ['sum']).RNF
fogo.columns = ['TMax','TMin','Rain']
fogo['Fogo'] = (fogo['TMax']>24) \
        | ((fogo['TMax']>21) & (fogo['TMin']>12)) \
        | ((fogo['TMax']>18) & (fogo['TMin']>10) & (fogo['Rain']>2))

def f(x):    
if (fogo['TMax']>24):
    return 'a'
elif ((fogo['TMax']>21) & (fogo['TMin']>12)):
    return 'b'
elif ((fogo['TMax']>18) & (fogo['TMin']>10) & (fogo['Rain']>2)):
    return 'c'

fogo['Causa'] = fogo.apply(f, axis=1)


    TMax    TMin    Rain    Fogo            Causa
2012-04-01   21.6    10.3    0.8     False    empty
2012-04-02   19.3    9.5     0.0     False    empty
2012-04-03   16.2    10.1    0.2     False    empty
2012-04-04   16.7    11.4    0.2     False    empty
2012-04-05   14.0    5.9     2.9     False    empty

but it returns the following error

'The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Could you help me?

Thank you

Hugo

Upvotes: 1

Views: 172

Answers (1)

EdChum
EdChum

Reputation: 393863

So the first problem in your code is that you are calling apply and setting param axis=1 this applies your function row-wise which is fine.

However, in your function you are referencing the whole dataframe when you call fogo['TMax'] > 24, this is why you get the error as you are applying your function row-wise but then trying to reference the entire dataframe so it confused.

So you could change your function to this:

def f(x):    
    if (x['TMax']>24):
        return 'a'
    elif ((x['TMax']>21) & (x['TMin']>12)):
        return 'b'
    elif ((x['TMax']>18) & (x['TMin']>10) & (x['Rain']>2)):
        return 'c'

However, seeing as you are just setting three values for 3 different conditions then you could just use boolean indexing to create a mask and just set all rows that meet your conditions.

so:

fogo.loc[fogo['TMax']> 24,'Causa'] = 'a'
fogo.loc[(fogo['TMax']> 21) & (fogo['TMin'] > 12),'Causa'] = 'b'
fogo.loc[(fogo['TMax']> 18) & (fogo['TMin'] > 10) & (fogo['Rain'] > 2),'Causa'] = 'c'

This will be much faster then iterating row-wise especially for large dataframes.

So on your example data I can do this:

In [10]:

fogo.loc[fogo['TMax']> 21,'Causa'] = 'a'
fogo.loc[(fogo['TMax']> 21) & (fogo['TMin'] > 11),'Causa'] = 'b'
fogo.loc[(fogo['TMax']> 11) & (fogo['TMin'] > 5) & (fogo['Rain'] > 2),'Causa'] = 'c'
fogo
Out[10]:
            TMax  TMin  Rain   Fogo  Causa
2012-04-01  21.6  10.3   0.8  False      a
2012-04-02  19.3   9.5   0.0  False  empty
2012-04-03  16.2  10.1   0.2  False      b
2012-04-04  16.7  11.4   0.2  False      b
2012-04-05  14.0   5.9   2.9  False      c

[5 rows x 5 columns]

Upvotes: 1

Related Questions