Regex для сравнения и извлечения букв алфавита с использованием Python - PullRequest
0 голосов
/ 14 декабря 2018

Привет, у меня есть набор данных, как показано ниже:

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

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Я думаю, это можно сделать с помощью встроенных строковых функций.Попробуйте это!

def f(mess):
    p1 = mess.find('yl')
    p2 = mess.find('rd')
    return int(mess[p1+3:].split(' ')[0]),int(mess[p2+3:].split(' ')[0])

df['vals'] =df['Message'].apply(f) 

df['status'] = df.apply(lambda row:  'g' if min(row['vals']) > row.time \
                        else 'y' if row.vals[1]>row.time  \
                        else 'r', axis=1)

print(df)

вывод:

  Format                  Message  time      vals status
0      A    ab@1 yl@5 rd@20 pp@40     3   (5, 20)      g
1      B  bc@1  yl@20 ss@25 rd@50    21  (20, 50)      y
2      C          cc@1 yl@9 rd@20    22   (9, 20)      r
0 голосов
/ 14 декабря 2018

Ваш вопрос - это действительно ряд вопросов.Из тега «dataframe» видно, что вы делаете это с помощью панд.Регулярное выражение, о котором вы спрашиваете, может добавить дополнительные числа для 'yl' и 'rd' (если они есть, я предполагаю, что они всегда есть)Но регулярное выражение обычно не выполняет математических или числовых сравнений, так что это третий бит.

Регулярное выражение, совпадающее с числовым значением для 'yl' (предполагается, что целое число, а не число с плавающей точкой):

r'yl@(\d+)'

Вы можете извлечь их в одном выражении, но при этом можно предположить, что они всегда находятся в одном и том же порядке, или стать сложным регулярным выражением.

Чтобы обеспечить совпадение только yl@5, но что-токак и xyl@5, нет, вы можете добавить некоторые ограничения для начала (требуется пробел или начало строки) и конца (требуется пробел или конец строки):

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

Или, если у вас есть ситуации, когдаyl является пространством имен, как и 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 и заполнения егорезультат determine_status для каждой строки в DataFrame.

Вы не указали, какую версию Python вы используете, но если это версия до Python 3.6, вы обнаружите, что выражения типа f'{tag} not in message.' не будет работать - вместо этого вы будете использовать что-то вроде '{tag} not in message.'.format(tag=tag).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...