【问题标题】:Using defined strings for regex searching with python使用定义的字符串使用 python 进行正则表达式搜索
【发布时间】:2020-03-04 03:01:20
【问题描述】:

我希望增强下面的脚本。我想知道是否可以使用已定义的字符串(例如'G', 'SG', 'PF', 'PG', 'SF', 'F', 'UTIL', 'C')来搜索它们之间的名称,然后使用提供的这些字符串作为列的名称。我在当前设置中遇到的问题是,如果名称以两个大写字母开头,如下例所示,它不知道区别。能够设置当前字符串以使用正则表达式进行搜索,然后返回它们之间的文本,我认为这将是改进功能的下一步。

上一个问题: Python: Regex or Dictionary

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)

输出:

期望的输出:

我想将此脚本用于具有其他字符串的其他数据,这样可以更轻松地定义我要查找的内容。正如我们从输入数据框中看到的,搜索字符串的位置顺序不同。上面的脚本会将它们按顺序排列,我们可以在所需的输出数据框中看到。

【问题讨论】:

  • 您不再需要位置编号了吗?正如上次发布的那样,这是一项要求。
  • 感谢您的提问。要在其他格式中使用它,编号是必要的。离开它是理想的,使其具有普遍性。例如,将有另一个具有三个相同的“OF”、“OF”、“OF”。
  • 您的输入是否必须是一个数据框,或者您是否总是将字符串列表传递给它?
  • 我正在考虑手动设置脚本中的列表以使其更容易。

标签: python regex


【解决方案1】:

我们可以简单地更新您的正则表达式来检查大写单词是否不直接与前一个单词相邻。

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 

【讨论】:

  • 问题仍然存在于 III、II、I 的第一、第二和第三。这是一个包含它们的快速df。 dk_cont_lineup_df = pd.DataFrame(data=np.array([["PG CJ McCollum C Nikola Vucevic UTIL Jonas Valanciunas PF Robert Covington G Collin Sexton SG RJ Barrett SF Royce O'Neale F James Ennis III"],["PG CJ McCollum C Nikola Vucevic UTIL Jonas Valanciunas PF Robert Covington G Collin Sexton SG RJ Barrett SF Royce O'Neale F James Ennis II"],["PG CJ McCollum C Nikola Vucevic UTIL Jonas Valanciunas PF Robert Covington G Collin Sexton SG RJ Barrett SF Royce O'Neale F James Ennis I"]]))
  • 有什么问题?我刚刚运行了df,它输出正确吗?
  • 在这个例子中你是对的。如果你把F James Ennis III 放在SF Royce O`Neale 前面,或者放在最后一个位置以外的任何地方,那就是它打破的地方。
  • 仅在regex 下重新提出这个问题可能是更好的选择,因为您想要实现的一切都是regex。发布一个字符串,并找到除III 用例之外的所有标题匹配项。此问题已按要求回答,不太可能收到针对该用例的新答案。
  • (\s|^)(?:UTIL|PF|SG|SF|PG|C|G|F)(?=\s) 这将正确解析,但不会将它们用作标题,也不会将它们组织到正确的列中。只是分开。
猜你喜欢
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
相关资源
最近更新 更多