首页 > 解决方案 > 从 DataFrame.loc 访问 pandas 数据框中的列表

问题描述

我正在使用一个包含“tchname”列的数据库,每个条目都包含一个字符串,例如“John Smith”或“Mr John Adam Smith”,其中第一个或第二个单词(取决于是否有敬语)每个字符串是名字,最后一个词是姓氏。

我想做的是创建两个新列,“名字”和“姓氏”。获取姓氏很容易,但是我获取名字的方法虽然有效,但感觉非常hacky:

import pandas as pd

# Typical data example:
data = {'tchname': ['MISS NANDA DEVI', 'RAJIK HUSSAIN-III',
                    'MAJJI VENKATA KANAKA DURGA RANI']}
df = pd.DataFrame(data)

# Split words in teacher names into list.
df['tchname'] = df['tchname'].str.split()

# Extract first word from tchname lists.
df['firstname'] = df['tchname'].str[0].str.title()

# If firstname matches item in honorific, replace with second tchname entry
df['placeholder'] = df['tchname'].str[1].str.title()
honorific = ['Dr', 'Miss', 'Mr', 'Mrs', 'Ms']
df.loc[df['firstname'].isin(honorific), 'firstname'] \
    = df.loc[df['firstname'].isin(honorific), 'placeholder']
df = df.drop(columns='placeholder')

# Extract last name from tchname lists.
df['surname'] = df['tchname'].str[-1].str.title()

现在,这正确地将名称识别为“Nanda Devi”、“Rajik Hussain-Iii”和“Majji Rani”。通过使用“占位符”来做到这一点对我来说似乎是一种 hacky 方法。只需几秒钟即可完成(超过数百万个条目的数据库),但是由于它不必要地将无效的名字(例如“小姐”)写入数据库,然后覆盖它们,我想知道是否有我可以采取更好的方法,所以我只在每个条目上迭代并写入数据库一次?

标签: pythonpython-3.xpandasdataframe

解决方案


感谢 Alexander Cécile 关于使用正则表达式的建议。由于正则表达式的性能不佳,我试图避免这种情况,但是这里有一个基于它的解决方案:

import numpy as np
import pandas as pd

# Typical data example:
data = {'tchname': ['MISS NANDA DEVI', 'RAJIK HUSSAIN-III',
                    'MAJJI VENKATA KANAKA DURGA RANI']}
df = pd.DataFrame(data)

# Set firstname to first or second word of tchname based on honorific presence.
df['firstname'] = np.where(df['tchname'].str.match(
    '^(Dr|Miss|Mr|Mrs|Ms) ', case=False),
    df['tchname'].str.split().str[1].str.capitalize(),
    df['tchname'].str.split().str[0].str.capitalize())

df['surname'] = df['tchname'].str.split().str[-1].str.capitalize()

我想说代码肯定更清晰,从可维护性的角度来看可能是一个不错的解决方案,但是正如预期的那样,这比原来的运行时间慢(执行时间约为 6.3 秒,而问题中的代码约为 5.4 秒)我的机器使用大型数据集),所以除非没有更好的替代方案建议,否则我不会接受这个答案。


推荐阅读