如果包含一个空格,Pandas会将名称列拆分为名字和姓氏

时间:2016-07-18 13:22:13

标签: python pandas

让我们说我有一个包含如下名字的pandas DataFrame:

name_df = pd.DataFrame({'name':['Jack Fine','Kim Q. Danger','Jane Smith', 'Juan de la Cruz']})

    name
0   Jack Fine
1   Kim Q. Danger
2   Jane Smith
3   Juan de la Cruz

我希望将name列拆分为first_namelast_name如果名称中有一个空格。否则,我希望将全名推入first_name

所以最终的DataFrame看起来应该是这样的:

  first_name     last_name
0 Jack           Fine
1 Kim Q. Danger
2 Jane           Smith
3 Juan de la Cruz

我已经尝试通过首先应用以下函数来返回可以拆分为名字和姓氏的名称来实现此目的:

def validate_single_space_name(name: str) -> str:
    pattern = re.compile(r'^.*( ){1}.*$')
    match_obj = re.match(pattern, name)
    if match_obj:
        return name
    else:
        return None

然而,将此函数应用于我的原始name_df会导致一个空的DataFrame,而不是一个由可以拆分和Nones的名称填充的数据框。

帮助我了解当前的工作方法,或者推荐采用不同方法的解决方案!

2 个答案:

答案 0 :(得分:4)

您可以使用str.split拆分字符串,然后使用str.len测试拆分数量,并将其用作布尔掩码,只分配那些具有拆分最后一个组件的行:

In [33]:
df.loc[df['name'].str.split().str.len() == 2, 'last name'] = df['name'].str.split().str[-1]
df

Out[33]:
              name last name
0        Jack Fine      Fine
1    Kim Q. Danger       NaN
2       Jane Smith     Smith
3  Juan de la Cruz       NaN

修改

您可以使用参数split调用expand=True,这只会填充名称长度恰​​好为2个名称的位置:

In [16]:
name_df[['first_name','last_name']] = name_df['name'].loc[name_df['name'].str.split().str.len() == 2].str.split(expand=True)
name_df

Out[16]:
              name first_name last_name
0        Jack Fine       Jack      Fine
1    Kim Q. Danger        NaN       NaN
2       Jane Smith       Jane     Smith
3  Juan de la Cruz        NaN       NaN

然后,您可以使用fillna替换丢失的名字:

In [17]:
name_df['first_name'].fillna(name_df['name'],inplace=True)
name_df
​
Out[17]:
              name       first_name last_name
0        Jack Fine             Jack      Fine
1    Kim Q. Danger    Kim Q. Danger       NaN
2       Jane Smith             Jane     Smith
3  Juan de la Cruz  Juan de la Cruz       NaN

答案 1 :(得分:0)

我在IndexError: list index out of range上遇到了一些问题,因为名称可能是testkk和其他怪异的用户输入。所以最终得到这样的东西:

items['fullNameSplitLength'] = items['fullName'].str.split().str.len()
items['firstName'] = items['lastName'] = ''
items.loc[
  items['fullNameSplitLength'] >= 1,
  'firstName'
] = items.loc[items['fullNameSplitLength'] >= 1]['fullName'].str.split().str[0]
items.loc[
  items['fullNameSplitLength'] >= 2,
  'lastName'
] = items.loc[items['fullNameSplitLength'] >= 2]['fullName'].str.split().str[-1]