python - 当不是每个人都有中间名时,将名字解析为名字、中间名、姓氏

标签 python python-3.x pandas text

我有一个看起来有点像这样的 df:

name                           id
John McNamara                  3498
Jane Adams, M.D.               6725
Nour Abd Almohsen Jr M.D.      0197
Alex Ambrose PhD               3287
Nancy Ann Brown, MPH, PhD      9127
Kathy W.                       4389
Jack Joshua Smith White        6756

我需要将姓名列分为名字、中间名、姓氏、后缀和标题。通常我会使用 .str.split 之类的东西,但在这种情况下,并不是每个人都有中间名、后缀或标题。此外,某些值有逗号分隔,而其他值则没有。有什么办法可以解释这些差异吗?

理想情况下,我希望我的输出如下所示:

first_name middle_name last_name    suffix title     id
John                   McNamara                      3498
Jane                   Adams               M.D.      6725
Nour       Abd         Almohsen     Jr     M.D.      0197
Alex                   Ambrose             PhD       3287
Nancy      Ann         Brown               MPH, PhD  9127
Jack       J           Smith White

编辑:我知道这需要多个步骤,包括可能删除标点符号。我发现一些特别棘手的事情:

  • 如果我使用类似 pd.concat([df['id'], df['name'].str.split(' ', Expand=True)], axis=1) 像 Jack Joshua Smith White 这样的名字最终会被分成多个“中间名”列,其中 Smith 与所有其他人的姓氏位于同一列中。有没有办法让最后一个字符串自动进入最后一列? 我尝试使用 df['last_name'].fillna(df['middle_name'], inplace=True) 之类的东西来解决这个问题,但这不起作用,因为有时人们有多个“中间名”,我需要一种选择非 None 的最新中间名的方法。

最佳答案

如果您能够获取数据框中所有可能的标题,则可以像这样解析您的名称:

import pandas as pd

# Create the dataframe with provided sample data
names = ['John McNamara','Nour Abd Almohsen Jr M.D.','Nancy Ann Brown, MPH, PhD','MPH']
med_id = ['3498', '6725', '0197', '3287', '9127','']

df = pd.DataFrame(list(zip(names, med_id)), columns =['name', 'id']) 
names = df['name'].to_list()


# List to fill up given the dataframe content
suffix = ['M.D.', 'PhD', 'MPH']
garbages = [',']

# iterate over all the name in your list
clean_names = []
first_name = []
middle_name = []
last_name = []
title = []

# Remove suffix and junk from the names
for name in names:
    to_remove = suffix + garbages
    clean_name = name
    for element in to_remove:
        clean_name = clean_name.replace(element, '')
    clean_names.append(clean_name)

# split the clean_names into first middle and last name
for (name,original_name) in zip(clean_names,names):
    data = name.split()

    # error checking for messed up entries
    if len(data) < 2:
        first_name.append("")
        middle_name.append("")
        last_name.append("")
        title.append("")
        print("Entry : " + original_name + " is malformed")
        continue

    # Add the right firstname lastname and middle name structure
    first_name.append(data[0])
    if len(data) == 2:
        middle_name.append("")
        last_name.append(data[1])
    else:
        middle_name.append(data[1])
        last_name.append(" ".join(data[2:]))

    # Add the right title
    title.append(' ,'.join([suf for suf in suffix if suf in original_name]))

df['first_name'] = first_name
df['middle_name'] = middle_name
df['last_name'] = last_name
df['title'] = title
df = df.drop(columns = ['name','id'])

print(df)

以下是您提供的输出,包括有问题的条目: enter image description here

但是您的数据集在标点符号方面看起来非常不规则

关于python - 当不是每个人都有中间名时,将名字解析为名字、中间名、姓氏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59437493/

相关文章:

python - 包的导入可以在 IPython shell 中使用,但不能在 Jupyter Notebook 中使用

django - 返回带有当前 FormWizard 数据的新 FormWizard

从类列表中输入 Python

python - 应用特定于行的条件的有效方法

python - Pandas:将日期间隔转换并合并到面板中的虚拟变量中

python - 当未产生该值时,有没有办法更新生成器循环条件?

multithreading - ThreadPoolExecutor 与来自两个列表的所有参数

python - 在Excel文件中用字符串对列进行排序[使用python,pandas]

python - 使用 python for 循环创建时间列表

python - 将多个文件合并到一个新文件中