Skip to main content
 首页 » 编程设计

python之如何将正则表达式函数应用于数据框列以返回值

2024年09月03日28落叶无声

我正在尝试将正则表达式函数应用于数据框的列以确定性别代词。这是我的数据框的样子:

    name                                            Descrip 
0  Sarah           she doesn't like this because her mum... 
1  David                 he does like it because his dad... 
2    Sam  they generally don't like it because their par... 

这些是我为制作该数据框而运行的代码:

list_label = ["Sarah", "David", "Sam"] 
list_descriptions = ["she doesn't like this because her mum...", "he does like it because his dad...", "they generally don't like it because their parent..."] 
 
data3 = {'name':list_label, 'Descrip':list_descriptions} 
test_df = pd.DataFrame(data3) 

我试图通过在“描述”列上应用正则表达式函数来确定此人的性别。具体来说,这些是我想要实现的模式:

"male":"(he |his |him )", 
"female":"(she |her |hers )", 
"plural, or singular non-binary":"(they |them |their )" 

我写的完整代码如下:

此函数尝试匹配每个模式并返回行值描述中最常提到的性别代词的名称。每个性别代词在模式字符串中都有几个关键词(例如,他、她、他们)。这个想法是确定 max_gender,或者与 Descrip 列中的值中提及最多的模式组相关联的性别。因此,max_gender 可以采用以下三个值之一:男性 |女性 |复数,或单数非二进制。如果在整个 Descrip 行值中未识别出任何模式,则将返回“未知”。

import re 
def get_pronouns(text): 
    patterns = { 
        "male":"(he |his |him )", 
        "female":"(she |her |hers )", 
        "plural, or singular non-binary":"(they |them |their )" 
    } 
    max_gender = "unknown" 
    max_gender_count = 0 
    for gender in patterns: 
        pattern = re.compile(gender) 
        mentions = re.findall(pattern, text) 
        count_mentions = len(mentions) 
        if count_mentions > max_gender_count: 
            max_gender_count = count_mentions 
            max_gender = gender 
    return max_gender 
 
test_df["pronoun"] = test_df.loc[:, "Descrip"].apply(get_pronouns) 
print(test_df) 

但是,当我运行代码时,它显然无法确定性别代词。这显示在以下输出中:

    name                                            Descrip  pronoun 
0  Sarah           she doesn't like this because her mum...  unknown 
1  David                 he does like it because his dad...  unknown 
2    Sam  they generally don't like it because their par...  unknown 

有人知道我的代码有什么问题吗?

请您参考如下方法:

如果你想知道为什么你的代码不工作,像这样在你的函数中添加一个打印语句:

    for gender in patterns: 
        print(gender) 
        pattern = re.compile(gender) 

您的正则表达式也需要一些调整。例如,在 Pink Floyd 的歌曲 Breathe 的第一行中,Breathe, breathe in the air,您的正则表达式找到了两个男性代词。

可能还有其他问题,我不确定。


这是一个与您的解决方案非常相似的解决方案。正则表达式是固定的,字典被替换为元组列表等。


解决方案代码

import pandas as pd 
import numpy as np 
import re 
import operator as op 
 
names_list = ['Sarah', 'David', 'Sam'] 
descs_list = ["she doesn't like this because her mum...", 'he does like it because his dad...', 
              "they generally don't like it because their parent..."] 
 
df_1 = pd.DataFrame(data=zip(names_list, descs_list), columns=['Name', 'Desc']) 
 
pronoun_re_list = [('male', re.compile(r"\b(?:he|his|him)\b", re.IGNORECASE)), 
                   ('female', re.compile(r"\b(?:she|her|hers)\b", re.IGNORECASE)), 
                   ('plural/nb', re.compile(r"\b(?:they|them|their)\b", re.IGNORECASE))] 
 
 
def detect_pronouns(str_in: str) -> str: 
    match_results = ((curr_pron, len(curr_patt.findall(str_in))) for curr_pron, curr_patt in pronoun_re_list) 
    max_pron, max_counts = max(match_results, key=op.itemgetter(1)) 
    if max_counts == 0: 
        return np.NaN 
    else: 
        return max_pron 
 
 
df_1['Pronouns'] = df_1['Desc'].map(detect_pronouns) 

说明

代码

match_results 是一个生成器表达式。 curr_pron 代表“当前代词”,curr_patt 代表“当前模式”。如果我将其重写为创建列表的 for 循环,可能会使事情变得更清楚:

    match_results = [] 
    for curr_pron, curr_patt in pronoun_re_list: 
        match_counts = len(curr_patt.findall(str_in)) 
        match_results.append((curr_pron, match_counts)) 

for curr_pron, curr_patt in ... 正在利用具有几个不同名称的东西,通常是多重赋值或元组拆包。你可以在上面找到一篇不错的文章here .在这种情况下,它只是一种不同的写法:

    for curr_tuple in pronoun_re_list: 
        curr_pron = curr_tuple[0] 
        curr_patt = curr_tuple[1] 

正则表达式

每个人最喜欢的主题的时间;正则表达式!我使用一个名为 RegEx101 的精彩网站,你可以弄乱那里的模式,它让事情更容易理解。我已经建立了一个页面,其中包含一些测试数据和我将在下面介绍的正则表达式:https://regex101.com/r/Y1onRC/2 .

现在,让我们看一下我使用的正则表达式:\b(?:he|his|him)\b。

he|his|him 部分与您的部分完全相同,它匹配单词“he”、“his”或“him”。在您的正则表达式中,它被括号包围,我的正则表达式也在左括号后包含 ?: 。 (pattern stuff) 是 capturing group ,顾名思义,意味着它会捕获匹配的任何内容。由于这里我们实际上并不关心匹配的内容,只关心是否匹配,所以我们添加 ?: 创建一个非捕获组,不捕获(或保存)内容。

我说过正则表达式的 he|his|him 部分与您的相同,但这并不完全正确。您在每个代词后包含一个空格,大概是为了避免它与单词中间的字母 he 匹配。不幸的是,正如我上面提到的,它在句子 Breathe, breathe in the air 中找到了两个匹配项。我们的救星是 \b,它匹配 word boundaries .这意味着我们在 Words words he. 中捕获了 he,而 (he |his |him ) 没有。

最后,我们用 re.IGNORECASE 编译模式flag,我认为不需要太多解释,但如果我错了请告诉我。

以下是我如何用简单的英语描述这两种模式:

  • (he |his |him ) 匹配字母 he 后跟一个空格,his 后跟一个空格,或者 him 后跟一个空格,然后返回完整匹配项和一个组。
  • \b(?:he|his|him)\b 与 re.IGNORECASE 标志匹配单词 he, his 或 him,不分大小写,并返回完整匹配项。

希望已经足够清楚了,让我知道!


结果输出

    Name    Desc                                                  Pronouns 
--  ------  ----------------------------------------------------  ---------- 
 0  Sarah   she doesn't like this because her mum...              female 
 1  David   he does like it because his dad...                    male 
 2  Sam     they generally don't like it because their parent...  plural/nb 

如果您有任何问题,请告诉我:)