Applying an if else function to two string columns in python / pandas

Viewed 165

In my dataframe I have:

Name    Sex    Height
Jackie   F       Small
John     M       Tall

I have made the following function to apply to create a new column based off combinations:

def genderfunc(x,y):
    if x =='Tall' & y=='M':
        return 'T Male'
    elif x =='Medium' & y=='M':
        return 'Male'
    elif x =='Small' & y=='M':
        return 'Male'
    elif x =='Tall' & y=='F':
        return 'T Female'
    elif x =='Medium' & y=='F':
        return 'Female'
    elif x =='Small' & y=='F':
        return 'Female'
    else:
        return y

My line of code to apply this function:

df['GenderDetails'] = df.apply(genderfunc(df['Height'],df['Sex']))

and i get the following:

TypeError: Cannot perform 'rand_' with a dtyped [object] array and scalar of type [bool]

Any ideas on what im doing wrong here? this is my first go at using a function.

Thanks!

4 Answers

Here is another approach, using map.

map_ = {"TallM": "T Male", "SmallF": "Female"}

df['GenderDetails'] = (df['Height'] + df['Sex']).str.strip().map(map_)

     Name Sex Height GenderDetails
0  Jackie   F  Small        Female
1    John   M   Tall        T Male

or you can use np.select, if performance is a concern-

condlist = [(df['Height'] == 'Tall') & (df['Sex'] == 'M'),
            (df['Height'] == 'Medium') & (df['Sex'] == 'M'),
            (df['Height'] == 'Small') & (df['Sex'] == 'M'),
            (df['Height'] == 'Tall') & (df['Sex'] == 'F'),
            (df['Height'] == 'Medium') & (df['Sex'] == 'F'),
            (df['Height'] == 'Small') & (df['Sex'] == 'F')]
choiselist = [
    'T Male',
    'Male',
    'Male',
    'T Female',
    'Female',
    'Female'
]

df['GenderDetails'] = np.select(condlist, choiselist, df['Sex'])

You are close, need lambda function with axis=1 and because scalar processing use and:

def genderfunc(x,y):
    if x =='Tall' and y=='M':
        return 'T Male'
    elif x =='Medium' and y=='M':
        return 'Male'
    elif x =='Small' and y=='M':
        return 'Male'
    elif x =='Tall' and y=='F':
        return 'T Female'
    elif x =='Medium' and y=='F':
        return 'Female'
    elif x =='Small' and y=='F':
        return 'Female'
    else:
        return y

df['GenderDetails'] = df.apply(lambda x: genderfunc(x['Height'],x['Sex']), axis=1)
print (df)
     Name Sex Height GenderDetails
0  Jackie   F  Small        Female
1    John   M   Tall        T Male

Non loop solution is possible with helper DataFrame and left join:

#set values like need
L = [('Tall','M','T Male'), ('Small','F','Female')]
df1 = pd.DataFrame(L, columns=['Height','Sex','GenderDetails'])


df = df.merge(df1, how='left')
print (df)
     Name Sex Height GenderDetails
0  Jackie   F  Small        Female
1    John   M   Tall        T Male
Related