Использование определенных строк для поиска регулярных выражений с python - PullRequest
0 голосов
/ 04 марта 2020

Я хочу улучшить скрипт, который у меня есть ниже. Мне интересно, возможно ли использовать определенные строки, такие как 'G', 'SG', 'PF', 'PG', 'SF', 'F', 'UTIL', 'C', для поиска имен между ними, а затем использовать эти строки, указанные в качестве имени столбца. Проблема с текущей настройкой заключается в том, что если имя начинается с двух заглавных букв, как в примере ниже, оно не знает разницы. Возможность задавать текущие строки для поиска с помощью регулярных выражений, а затем возвращать текст между ними, я думаю, будет следующим шагом для улучшения функции.

Предыдущий вопрос: Python: регулярные выражения или словарь

import pandas as pd, numpy as np

dk_cont_lineup_df = pd.DataFrame(data=np.array([['G CJ McCollum SG Donovan Mitchell PF Robert Covington PG Collin Sexton SF Bojan Bogdanovic F Larry Nance Jr. UTIL Trey Lyles C Maxi Kleber'],['UTIL Nikola Vucevic PF Kevin Love F Robert Covington SG Collin Sexton SF Bojan Bogdanovic G Coby White PG RJ Barrett C Larry Nance Jr.']]))
dk_cont_lineup_df.rename(columns={ dk_cont_lineup_df.columns[0]: 'Lineup' }, inplace = True)


def calc_col(col):
    '''This function takes a string,
    finds the upper case letters or words placed as delimeter,
    converts it to a list,
    adds a number to the list elements if recurring.
    Eg. input list :['W','W','W','D','D','G','C','C','UTIL']
    o/p list: ['W1','W2','W3','D1','D2','G','C1','C2','UTIL']
    '''
    col_list = re.findall(" ?([A-Z]+) ", col)
    col_list2 = []
    for i_pos in col_list:
        cnt = col_list.count(i_pos)
        if cnt == 1:
            col_list2.append(i_pos)
        if cnt > 1:
            if i_pos in " ".join(col_list2):
                continue;
            col_list2 += [i_pos+str(k) for k in range(1,cnt+1)] 
    return col_list2


# START OF SPLIT LINEUP INTO SEPERATE COLUMNS
extr_row = dk_cont_lineup_df['Lineup'].replace(to_replace =" ?[A-Z]+ ", value="\n", regex = True) #split the rows on 
df_final = pd.DataFrame(columns = sorted(calc_col(dk_cont_lineup_df['Lineup'].iloc[0]))) #Create an empty data frame df3 with sorted columns
for i_pos in range(len(extr_row)): #traverse all the rows in the original dataframe and append the formatted rows to df3
    df_temp = pd.DataFrame((extr_row.values[i_pos].split("\n")[1:])).T
    df_temp.columns = calc_col(dk_cont_lineup_df['Lineup'].iloc[i_pos])
    df_temp= df_temp[sorted(df_temp)]
    df_final = df_final.append(df_temp)
df_final.reset_index(drop = True, inplace = True)

ВЫХОД:

enter image description here

Желаемый ВЫХОД:

enter image description here

Я хотел бы использовать этот скрипт для других данных, которые имеют другие строки, которые облегчили бы определение того, что я ищу. Как мы видим из входного фрейма данных, позиции строк поиска находятся не в том же порядке. Сценарий выше приведёт их в порядок, который мы можем увидеть в желаемом выходном кадре данных.

1 Ответ

0 голосов
/ 05 марта 2020

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

r"(?<![A-Z] )\b([A-Z]+) "

Обратите внимание, что мы добавили отрицательный вид сзади. Не совпадать, если предыдущее слово не [A-Z]

Более подробное объяснение приведенного выше регулярного выражения можно найти здесь; https://regex101.com/r/j6RbSP/1

Теперь вы можете обновить свой код, включив в него новые шаблоны регулярных выражений, не забудьте добавить r"" перед строкой.

import pandas as pd, numpy as np
import re

dk_cont_lineup_df = pd.DataFrame(data=np.array([['G CJ McCollum SG Donovan Mitchell PF Robert Covington PG Collin Sexton SF Bojan Bogdanovic F Larry Nance Jr. UTIL Trey Lyles C Maxi Kleber'],['UTIL Nikola Vucevic PF Kevin Love F Robert Covington SG Collin Sexton SF Bojan Bogdanovic G Coby White PG RJ Barrett C Larry Nance Jr.']]))
dk_cont_lineup_df.rename(columns={ dk_cont_lineup_df.columns[0]: 'Lineup' }, inplace = True)


def calc_col(col):
    '''This function takes a string,
    finds the upper case letters or words placed as delimeter,
    converts it to a list,
    adds a number to the list elements if recurring.
    Eg. input list :['W','W','W','D','D','G','C','C','UTIL']
    o/p list: ['W1','W2','W3','D1','D2','G','C1','C2','UTIL']
    '''
    col_list = re.findall(r"(?<![A-Z] )\b([A-Z]+) ", col)
    col_list2 = []
    for i_pos in col_list:
        cnt = col_list.count(i_pos)
        if cnt == 1:
            col_list2.append(i_pos)
        if cnt > 1:
            if i_pos in " ".join(col_list2):
                continue;
            col_list2 += [i_pos+str(k) for k in range(1,cnt+1)] 
    return col_list2


extr_row = dk_cont_lineup_df['Lineup'].replace(to_replace =r"(?<![A-Z] )\b([A-Z]+) ", value="\n", regex = True) #split the rows on 
df_final = pd.DataFrame(columns = sorted(calc_col(dk_cont_lineup_df['Lineup'].iloc[0])))

for i_pos in range(len(extr_row)): #traverse all the rows in the original dataframe and append the formatted rows to df3
    df_temp = pd.DataFrame((extr_row.values[i_pos].split("\n")[1:])).T
    df_temp.columns = calc_col(dk_cont_lineup_df['Lineup'].iloc[i_pos])
    df_temp= df_temp[sorted(df_temp)]
    df_final = df_final.append(df_temp)
df_final.reset_index(drop = True, inplace = True)

print(df_final.to_string())

Производит желаемый результат:

                 C                  F             G                 PF              PG                 SF                 SG             UTIL
0      Maxi Kleber   Larry Nance Jr.   CJ McCollum   Robert Covington   Collin Sexton   Bojan Bogdanovic   Donovan Mitchell       Trey Lyles 
1  Larry Nance Jr.  Robert Covington    Coby White         Kevin Love      RJ Barrett   Bojan Bogdanovic      Collin Sexton   Nikola Vucevic 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...