Skip to content Skip to sidebar Skip to footer

Python Combining Names With Missing Values

I have a pandas dataframe of names as shown. data = {'firstname': {0: 'Sassa', 1: 'Jennifer', 2: 'Jennifer', 3: 'Jennifer', 4: 'Vanessa', 5: 'Alexander', 6: 'Alexander', 7: 'Alexan

Solution 1:

Do you know about Python's string functions? you can combine these with pandas methods.

lets use stack along the index to remove any NaN values.

we can use groupby and ' '.join to create your full name column

df['PersonName' ] = df.stack().groupby(level=0).agg(' '.join)

print(df)

   firstname othername     surname              PersonName
0      Sassa      NaN  Radomirovic       Sassa Radomirovic
1   Jennifer      NaN        Catto          Jennifer Catto
2   Jennifer      NaN        Catto          Jennifer Catto
3   Jennifer      NaN        Catto          Jennifer Catto
4    Vanessa      NaN        Pinho           Vanessa Pinho
5  Alexander   Stuart        Clark  Alexander Stuart Clark
6  Alexander   Stuart        Clark  Alexander Stuart Clark
7  Alexander   Stuart        Clark  Alexander Stuart Clark

another, more verbose method would be to fill your columns and then replace all white space with a single space.

names = (
    df["firstname"] + " " + df["othername"].fillna("") + " " + df["surname"]
).replace("\s+", " ", regex=True)

print(names)

0         Sassa Radomirovic
1            Jennifer Catto
2            Jennifer Catto
3            Jennifer Catto
4             Vanessa Pinho
5    Alexander Stuart Clark
6    Alexander Stuart Clark
7    Alexander Stuart Clark

Solution 2:

I needed same thing at work and had used str.cat() method as shown below. @Datanovice were slightly slower

 (df.firstname.str.cat(df.othername.fillna(''), sep=' ')).str.cat(df.surname, sep=' ').str.replace('  ',' ')



firstname othername      surname              personname
0      Sassa       NaN  Radomirovic      Sassa  Radomirovic
1   Jennifer       NaN        Catto         Jennifer  Catto
2   Jennifer       NaN        Catto         Jennifer  Catto
3   Jennifer       NaN        Catto         Jennifer  Catto
4    Vanessa       NaN        Pinho          Vanessa  Pinho
5  Alexander    Stuart        Clark  Alexander Stuart Clark
6  Alexander    Stuart        Clark  Alexander Stuart Clark
7  Alexander    Stuart        Clark  Alexander Stuart Clark

Timing

@wwnde

 %timeit (df.firstname.str.cat(df.othername.fillna(''), sep=' ')).str.cat(df.surname, sep=' ').str.replace('  ',' ')
    997 µs ± 14.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

@Datanovice 1

%timeit df['PersonName' ] = df.stack().groupby(level=0).agg(' '.join)
3.5 ms ± 76.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

@Datanovice 1

%timeit df['PersonName' ] = df.stack().groupby(level=0).agg(' '.join)

1.34 ms ± 178 µs per loop (mean ± std. dev. of7 runs, 1000 loops each)

@Scott Boston

%timeit (df['firstname'].str.cat(df[['othername', 'surname']], sep=' ', na_rep='').replace('\s\s', ' ', regex=True))
1.54 ms ± 133 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Solution 3:

TRY: (Not a good solution though)

df['name'] =(df['firstname'].fillna('') + ' ' + df['othername'].fillna('')+' ' +df['surname'].fillna('')).str.strip(' ')

df:

    firstname   othername   surname     name
0   Sassa       NaN         Radomirovic Sassa Radomirovic
1   Jennifer    NaN         Catto       Jennifer Catto
2   Jennifer    NaN         Catto       Jennifer Catto
3   Jennifer    NaN         Catto       Jennifer Catto
4   Vanessa     NaN         Pinho       Vanessa Pinho
5   Alexander   Stuart      Clark       Alexander Stuart Clark
6   Alexander   Stuart      Clark       Alexander Stuart Clark
7   Alexander   Stuart      Clark       Alexander Stuart Clark

Solution 4:

I think you can also use, .str.cat like this:

(df['firstname'].str.cat(df[['othername', 'surname']], sep=' ', na_rep='')
                .replace('\s\s', ' ', regex=True))

Output:

0         Sassa Radomirovic
1            Jennifer Catto
2            Jennifer Catto
3            Jennifer Catto
4             Vanessa Pinho
5    Alexander Stuart Clark
6    Alexander Stuart Clark
7    Alexander Stuart Clark
Name: firstname, dtype: object

Adding Timings:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from timeit import timeit

data = {'firstname': {0: 'Sassa', 1: 'Jennifer', 2: 'Jennifer', 3: 'Jennifer', 
                      4: 'Vanessa', 5: 'Alexander', 6: 'Alexander', 7: 'Alexander'}, 
        'othername': {0: np.nan, 1: np.nan, 2: np.nan, 3: np.nan, 4: np.nan, 5: 'Stuart', 6: 'Stuart', 7: 'Stuart'}, 
        'surname': {0: 'Radomirovic', 1: 'Catto', 2: 'Catto', 3: 'Catto', 4: 'Pinho', 5: 'Clark', 6: 'Clark', 7: 'Clark'}}

df = pd.DataFrame(data)

defdn_1(d):
    return d.stack().groupby(level=0).agg(' '.join)
    
defdn_2(d):
    return (d["firstname"] + " " + d["othername"].fillna("") + " " + d["surname"]).replace("\s+", " ", regex=True)

defsb(d):
    return (df['firstname'].str.cat(df[['othername', 'surname']], sep=' ', na_rep='')
                .replace('\s\s', ' ', regex=True))

defww(d):
    return  (df.firstname.str.cat(df.othername.fillna(''), sep=' ')).str.cat(df.surname, sep=' ').str.replace('  ',' ')

#def pg(d):#    return (df['firstname'].fillna('') + ' ' + df['othername'].fillna('')+' ' +df['surname'].fillna('')).str.strip(' ')# Not equivalent result 

res = pd.DataFrame(
    index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
    columns='dn_1 dn_2 sb ww'.split(),
    dtype=float
)

for i in res.index:
    d = pd.concat([df]*i)
    for j in res.columns:
        stmt = '{}(d)'.format(j)
        setp = 'from __main__ import d, {}'.format(j)
        print(stmt, d.shape)
        res.at[i, j] = timeit(stmt, setp, number=100)

# res.groupby(res.columns.str[4:-1], axis=1).plot(loglog=True);
res.plot(loglog=True);

Chart:

enter image description here

Solution 5:

Try:

df['personname'] = str()
for i, row in df.iterrows():
    row.fillna('na', inplace=True)
    df['personname'][i] = f"{' '.join([name for name in row if name != 'na'])}".strip()

Output:

   firstname othername      surname              personname
0      Sassa        na  Radomirovic       Sassa Radomirovic
1   Jennifer        na        Catto          Jennifer Catto
2   Jennifer        na        Catto          Jennifer Catto
3   Jennifer        na        Catto          Jennifer Catto
4    Vanessa        na        Pinho           Vanessa Pinho
5  Alexander    Stuart        Clark  Alexander Stuart Clark
6  Alexander    Stuart        Clark  Alexander Stuart Clark
7  Alexander    Stuart        Clark  Alexander Stuart Clark

Post a Comment for "Python Combining Names With Missing Values"