Skip to main content
 首页 » 编程设计

python之正则表达式使用python比较和提取字母字符

2024年09月03日40Free-Thinker

您好,我有一个如下所示的数据集:

Format,Message,time 
A,ab@1 yl@5 rd@20 pp@40,3 
B,bc@1 gn@7 yl@20 ss@25 rd@50, 21 
C,cc@1 yl@9 rd@20, 22 

我想使用从消息的 yl 和 rd 中提取的数字,然后比较它的数字(例如 yl@5 ---> 5)和时间列的数字。因此,如果第 1 行、第 3 行将与第 5 行和第 20 行进行比较。因此,如果它小于两个元素,它将被分配一个值 g。如果时间为7,则赋值y,如果时间为20及以上,则赋值为r。

所以会这样

Format,Message,time,status 
A,ab@1 yl@5 rd@20 pp@40,3,g 
B,bc@1 gn@7 yl@20 ss@25 rd@50,21,y 
C,cc@1 yl@9 rd@20,22,r 

请您参考如下方法:

您的问题实际上是一些问题。从“dataframe”标签来看,您似乎是在使用 pandas 执行此操作。您询问的正则表达式可能会增加“yl”和“rd”的数字(如果有的话,我假设它们总是存在)。但是正则表达式通常不进行数学或数值比较,所以这是第三位。

匹配“yl”数值的正则表达式(假设是整数,不是 float ):

r'yl@(\d+)' 

您可以将它们提取到单个表达式中,但这会假设它们始终处于相同的顺序,或者成为一个复杂的正则表达式。

为了确保只有 yl@5 被匹配,而像 xyl@5 这样的东西不被匹配,您可以在开头添加一些限制(需要空格或行首) 和结尾(需要空格或行尾):

r'(^|\s)yl@(\d+)($|\s)' 

或者,如果您遇到 yl 是 namespace 的情况,例如 a:yl,您也可以添加它:

r'(^|\s)([a-z]+:)?l@(\d+)($|\s)' 

然而,这一切只是使用正则表达式语言构建更具体的表达式。我喜欢使用(无从属关系)编写正则表达式的一个非常好的工具是 RegexBuddy,但也有非常好的在线工具,例如 https://regex101.com/ .

在代码示例中基本上按照您的建议使用:

import re 
from pandas import DataFrame 
 
df = DataFrame({ 
    'Format': ['A', 'B', 'C'], 
    'Message': ['ab@1 yl@5 rd@20 pp@40', 'bc@1 gn@7 yl@20 ss@25 rd@50', 'cc@1 yl@9 rd@20'], 
    'time': [3, 21, 22] 
}) 
 
 
def determine_status(row): 
    def find(tag, message): 
        match = re.search(rf"{tag}@(\d+)", message) 
        if match: 
            return match.group(1) 
        else: 
            raise ValueError(f'{tag} not in message.') 
 
    yl = int(find('yl', row['Message'])) 
    rd = int(find('rd', row['Message'])) 
 
    time = int(row['time']) 
    if time < yl < rd: 
        return 'g' 
    if yl <= time < rd: 
        return 'y' 
    return 'r' 
 
 
df['status'] = df.apply(determine_status, axis=1) 
 
print(df) 

find 函数接受一个标签和一条消息,并使用正则表达式为消息中的标签生成数值。

determine_status 函数就是这样做的 - 它需要来自 DataFrame 的一行,并将使用 Message 和 time 列来确定状态并将其返回。

df.apply 然后用于创建一个新的 status 列,并为 DataFrame 中的每一行填充 determine_status 的结果.

您没有指定您使用的 Python 版本,但如果它是 Python 3.6 之前的版本,您会发现像 f'{tag} 这样的表达式不在消息中。'不会工作 - 相反你会使用类似 '{tag} not in message.'.format(tag=tag).