Check string inside column wrong behaviour - Pandas

Viewed 55

I have the following dataframe:

import pandas as pd 

df = pd.DataFrame ({
    'Name':['Unable host=test1, status=c0000192','Unable host=test2, status=22228001','Unable host=test3, status=c000018d'],
    'Error':['NaN','NaN','NaN']
    })


print(df)
                                   Name Error
0  Unable host=test1, status=c0000192   NaN
1  Unable host=test2, status=22228001   NaN
2  Unable host=test3, status=c000018d   NaN

The code should follow the below if statements:

import pandas as pd 

df = pd.DataFrame ({
    'Name':['Unable host=test1, status=c0000192','Unable host=test2, status=22228001','Unable host=test3, status=c000018d'],
    'Error':['NaN','NaN','NaN']
    })

if df['Name'].str.contains('status=c000018d').any():
    df['Error'] = 'Trust Failure'

elif df['Name'].str.contains('status=22228001').any():
    df['Error'] = 'No creds'

else:
    df['Error'] = 'Other'

print(df)

The output should be:

                                   Name          Error
0  Unable host=test1, status=c0000192  Other
1  Unable host=test2, status=22228001  No creds
2  Unable host=test3, status=c000018d  Trust Failure

Instead, I get:

                                   Name          Error
0  Unable host=test1, status=c0000192  Trust Failure
1  Unable host=test2, status=22228001  Trust Failure
2  Unable host=test3, status=c000018d  Trust Failure

Why is this happening? It's like the first if statement matches everything.

2 Answers

I think you are mixing things here, try this way:

df.loc[df['Name'].str.contains('status=c000018d'), 'Error'] = 'Trust Failure'
df.loc[df['Name'].str.contains('status=22228001'), 'Error'] = 'No creds'
df.loc[df['Name'] == 'NaN', 'Error'] = 'Other'

What you are doing returns true in the first if statement and fill all values with 'Trust Failure'.

np.select suits for this problem, which is a vectorized method for a multi-conditional column:

conditions = [df['Name'].str.contains('status=c000018d'), 
              df['Name'].str.contains('status=22228001')]
df['Error'] = np.select(conditions, choices=['Trust Failure', 'No creds'], default='Other')

                                 Name          Error
0  Unable host=test1, status=c0000192          Other
1  Unable host=test2, status=22228001       No creds
2  Unable host=test3, status=c000018d  Trust Failure
Related