首页 > 解决方案 > df 中的关键字计数:性能调整

问题描述

我有一个带有文本列的 df。说:

d = {'text': ["merry had a little lamb and a broken limb", "Little Jonathan found a chicken"]}
df = pd.DataFrame(data=d)

我还有一个包含约 400 个关键字的列表,例如:

observations_words_list = ["bent","block","broken"]

我希望查看有多少条记录在其文本中包含多个关键字,我正在这样做:

    df = df['text'].dropna().reset_index()
    df_len = len(df['text'])
    obs = set(observations_words_list)
    df['Observations'] = df['text'].apply(lambda x: len(set(str(x).lower().split()).intersection(obs)))
    obs_count = len(df[df['Observations'] > 0])/df_len

对于示例 df(实际上我读取了大约 0.5m 条记录的 csv),我希望新列的第一条记录为 1,第二条记录为 0,总体而言obs_count=0.5

运行时远非理想,我正在寻找一种更快的方法来处理这一步。

会喜欢你的想法。谢谢!

标签: pythonpandaslistperformance

解决方案


100k * df 为 290 毫秒

我了解您只想查看有多少记录包含一个或多个关键字,而绝对计数无关紧要。在这种情况下,有一个更好的(在我看来更优雅)的使用正则表达式的单行解决方案,它不会使用 apply 遍历数据:

d = {'text': ["merry had a little lamb and a broken limb", "Little Jonathan found a chicken"]*100000}
df = pd.DataFrame(data=d)

observations_words_list = ["bent","block","broken"]
obs = '|'.join(r"\b{}\b".format(x) for x in observations_words_list)
contains_obs = df['text'].str.contains(obs, flags=re.IGNORECASE, regex=True)
obs_count = sum(contains_obs)/len(df['text'])

如果您希望保留观察次数,可以使用“计数”来减少时间损失(410 毫秒):

df['Observations'] = df['text'].str.count(obs, flags=re.IGNORECASE)
obs_count = sum(df['Observations']>0)/len(df['text'])

推荐阅读