Python 使用正则表达式获取DataFrame列中子字符串的位置

Python 使用正则表达式获取DataFrame列中子字符串的位置,python,python-3.x,pandas,Python,Python 3.x,Pandas,我想使用正则表达式将字符串分解为数据帧列 csv数据样本[已更新]: Data;Code;Temp;.... 12 364 OPR 4 67474;;33;... 893 73 GDP hdj 747;;34;... hr 777 hr9 GDP;;30;... 463 7g 448 OPR;;28;... 所需情况:[已更新 Data | Code | Temp | ... --------------------------------------

我想使用正则表达式将字符串分解为数据帧

csv数据样本[已更新]:

Data;Code;Temp;....
12 364 OPR 4 67474;;33;...
893 73 GDP hdj 747;;34;...
hr 777 hr9 GDP;;30;...
463 7g 448 OPR;;28;...
所需情况:[已更新

Data           | Code        | Temp     | ...
------------------------------------------------
12 364         | OPR 4 67474 | 33       | ...
893 73         | GDP hdj 747 | 34       | ...
hr 777 hr9 GDP | NaN         | 30       | ...
463 7g 448 OPR | NaN         | 28       | ...
正则表达式:

code = re.compile('\sOPR.?[^$]|\sGDP.?[^$]')
仅当
OPR
GDP
不在字符串末尾时,我才需要拆分。 我在寻找一种基于比赛位置的分割方法。类似于:
match.start()

我尝试了类似的方法:
df['data'].str.contains(code,regex=True)
df['data']=df['data'].str.extract(code,expand=True)
str.find
似乎只对字符串有效,而对
re.Pattern
无效。我没有完成


我对熊猫还很陌生,所以请耐心听我说。

所以首先你要检查数据最后是否有GDP或OPR。如果没有,则可以使用分组正则表达式来获取所需的项。在这里,圆括号()中的内容表示一个组。我用语法P给它们命名,这是可选的

import re

data = ["12 364 OPR 4 67474;",
   "893 73 GDP hdj 747;",
   "hr 777 hr9 GDP;",
   "463 7g 448 OPR;"]

for item in data:
# first check if it ends with GPR; or OPR;
if re.search("GDP;|OPR;$", item):
    # as u specified it needs to be ignored
    print(item)
else:
    # now u can split into two parts - i am splitting in three but u can do use them however u like
    splited_match_obj = re.search("(?P<Data>.+)(?P<Value>OPR|GDP)(?P<Code>.+)", item)
    print(splited_match_obj["Data"], splited_match_obj["Value"], splited_match_obj["Code"] )

所以首先你要检查数据的末尾是否有GDP或OPR。如果没有,则可以使用分组正则表达式来获取所需的项。在这里,圆括号()中的内容表示一个组。我用语法P给它们命名,这是可选的

import re

data = ["12 364 OPR 4 67474;",
   "893 73 GDP hdj 747;",
   "hr 777 hr9 GDP;",
   "463 7g 448 OPR;"]

for item in data:
# first check if it ends with GPR; or OPR;
if re.search("GDP;|OPR;$", item):
    # as u specified it needs to be ignored
    print(item)
else:
    # now u can split into two parts - i am splitting in three but u can do use them however u like
    splited_match_obj = re.search("(?P<Data>.+)(?P<Value>OPR|GDP)(?P<Code>.+)", item)
    print(splited_match_obj["Data"], splited_match_obj["Value"], splited_match_obj["Code"] )

我对python相当陌生,因此如果这不是一个好方法,可能有人可以发表评论。我的思路是接受输入并逐行处理。删除尾随分号,因为输出中没有它。然后使用正则表达式将行拆分为一个空格字符,前提是其后跟OPR或GDP,且不在行的末尾。如果列表中只有一项,则在列表中附加NaN以填充第二列。然后我打印了格式

import re
data_string="""12 364 OPR 4 67474;
893 73 GDP hdj 747;
hr 777 hr9 GDP;
463 7g 448 OPR;
"""

data_list=data_string.splitlines()
for data in data_list:
    data_split=re.split("\s(?=(?:GDP|OPR)[^$])",data[:-1])
    if len(data_split)==1: data_split.append("NaN")
    print("%-20s|%-20s" % tuple(data_split))
输出

12 364              |OPR 4 67474         
893 73              |GDP hdj 747         
hr 777 hr9 GDP      |NaN                 
463 7g 448 OPR      |NaN                 
Original df:
                 data  code  Temp
0  12 364 OPR 4 67474  None    33
1  893 73 GDP hdj 747  None    34
2      hr 777 hr9 GDP  None    30
3      463 7g 448 OPR  None    28 

Updated df:
             data         code  Temp
0          12 364  OPR 4 67474    33
1          893 73  GDP hdj 747    34
2  hr 777 hr9 GDP         None    30
3  463 7g 448 OPR         None    28
根据问题编辑和评论进行更新

根据您对问题和评论的更新,您可以尝试以下方法。我建议您对此进行测试,并在执行更新之前检查任何边缘情况,或添加验证或条件检查

import pandas as pd
import re

source_data = {'data': ['12 364 OPR 4 67474', '893 73 GDP hdj 747', 'hr 777 hr9 GDP','463 7g 448 OPR'],
         'code': [None, None, None, None],
         'Temp': [33,34,30,28]
         }
df = pd.DataFrame.from_dict(source_data)
print("Original df:")
print(df, "\n")

row_iter=df.iterrows()
for index,row in row_iter:
    data=df.at[index,'data']
    data_split=re.split("\s(?=(?:GDP|OPR)[^$])",data)
    if len(data_split)==2:
        df.at[index,'data']=data_split[0]
        df.at[index,'code']=data_split[1]

print("Updated df:")
print(df)
输出

12 364              |OPR 4 67474         
893 73              |GDP hdj 747         
hr 777 hr9 GDP      |NaN                 
463 7g 448 OPR      |NaN                 
Original df:
                 data  code  Temp
0  12 364 OPR 4 67474  None    33
1  893 73 GDP hdj 747  None    34
2      hr 777 hr9 GDP  None    30
3      463 7g 448 OPR  None    28 

Updated df:
             data         code  Temp
0          12 364  OPR 4 67474    33
1          893 73  GDP hdj 747    34
2  hr 777 hr9 GDP         None    30
3  463 7g 448 OPR         None    28

我对python相当陌生,所以如果这不是一个好方法,可能有人可以发表评论。我的思路是接受输入并逐行处理。删除尾随分号,因为输出中没有它。然后使用正则表达式将行拆分为一个空格字符,前提是其后跟OPR或GDP,且不在行的末尾。如果列表中只有一项,则在列表中附加NaN以填充第二列。然后我打印了格式

import re
data_string="""12 364 OPR 4 67474;
893 73 GDP hdj 747;
hr 777 hr9 GDP;
463 7g 448 OPR;
"""

data_list=data_string.splitlines()
for data in data_list:
    data_split=re.split("\s(?=(?:GDP|OPR)[^$])",data[:-1])
    if len(data_split)==1: data_split.append("NaN")
    print("%-20s|%-20s" % tuple(data_split))
输出

12 364              |OPR 4 67474         
893 73              |GDP hdj 747         
hr 777 hr9 GDP      |NaN                 
463 7g 448 OPR      |NaN                 
Original df:
                 data  code  Temp
0  12 364 OPR 4 67474  None    33
1  893 73 GDP hdj 747  None    34
2      hr 777 hr9 GDP  None    30
3      463 7g 448 OPR  None    28 

Updated df:
             data         code  Temp
0          12 364  OPR 4 67474    33
1          893 73  GDP hdj 747    34
2  hr 777 hr9 GDP         None    30
3  463 7g 448 OPR         None    28
根据问题编辑和评论进行更新

根据您对问题和评论的更新,您可以尝试以下方法。我建议您对此进行测试,并在执行更新之前检查任何边缘情况,或添加验证或条件检查

import pandas as pd
import re

source_data = {'data': ['12 364 OPR 4 67474', '893 73 GDP hdj 747', 'hr 777 hr9 GDP','463 7g 448 OPR'],
         'code': [None, None, None, None],
         'Temp': [33,34,30,28]
         }
df = pd.DataFrame.from_dict(source_data)
print("Original df:")
print(df, "\n")

row_iter=df.iterrows()
for index,row in row_iter:
    data=df.at[index,'data']
    data_split=re.split("\s(?=(?:GDP|OPR)[^$])",data)
    if len(data_split)==2:
        df.at[index,'data']=data_split[0]
        df.at[index,'code']=data_split[1]

print("Updated df:")
print(df)
输出

12 364              |OPR 4 67474         
893 73              |GDP hdj 747         
hr 777 hr9 GDP      |NaN                 
463 7g 448 OPR      |NaN                 
Original df:
                 data  code  Temp
0  12 364 OPR 4 67474  None    33
1  893 73 GDP hdj 747  None    34
2      hr 777 hr9 GDP  None    30
3      463 7g 448 OPR  None    28 

Updated df:
             data         code  Temp
0          12 364  OPR 4 67474    33
1          893 73  GDP hdj 747    34
2  hr 777 hr9 GDP         None    30
3  463 7g 448 OPR         None    28

假设这是您的数据帧

    Data                Temp
0   12 364 OPR 4 67474  33
1   893 73 GDP hdj 747  34
2   hr 777 hr9 GDP      30
3   463 7g 448 OPR      28
您可以根据条件将extract与多个捕获组一起使用

df1[['Data', 'Code']] = df.loc[~df['Data'].str.endswith(('OPR','GDP')), 'Data'].str.extract('(.*)([A-Z]{3} .*)')
df2[['Data', 'Code']] = df.loc[df['Data'].str.endswith(('OPR','GDP')), 'Data'].str.extract('(.*[OPR|GDP]$)(.*)')
df[['Data', 'Code']] = pd.concat([df1,df2])

    Data            Temp    Code
0   12 364          33      OPR 4 67474
1   893 73          34      GDP hdj 747
2   hr 777 hr9 GDP  30  
3   463 7g 448 OPR  28  

假设这是您的数据帧

    Data                Temp
0   12 364 OPR 4 67474  33
1   893 73 GDP hdj 747  34
2   hr 777 hr9 GDP      30
3   463 7g 448 OPR      28
您可以根据条件将extract与多个捕获组一起使用

df1[['Data', 'Code']] = df.loc[~df['Data'].str.endswith(('OPR','GDP')), 'Data'].str.extract('(.*)([A-Z]{3} .*)')
df2[['Data', 'Code']] = df.loc[df['Data'].str.endswith(('OPR','GDP')), 'Data'].str.extract('(.*[OPR|GDP]$)(.*)')
df[['Data', 'Code']] = pd.concat([df1,df2])

    Data            Temp    Code
0   12 364          33      OPR 4 67474
1   893 73          34      GDP hdj 747
2   hr 777 hr9 GDP  30  
3   463 7g 448 OPR  28  


您想将Pandas数据帧的1列拆分为2列吗?
NaN
在第2列,需要
HR777 hr9 GDP
在第1列?我不明白规则。在正则表达式中,您可以使用特定匹配的数量,例如:
\d{3}
匹配组也会有帮助。@Rusty:是的,这就是我想要的。请看需要的situation@Zydnar:仅当
OPR
GDP
不在字符串末尾时,我才需要拆分。对于0和1,情况就是这样,对于2和3,它位于和,不需要拆分。是否希望将Pandas数据帧的1列拆分为2列?
NaN
位于第2列,而
HR777 hr9 GDP
位于第1列?我不明白规则。在正则表达式中,您可以使用特定匹配的数量,例如:
\d{3}
匹配组也会有帮助。@Rusty:是的,这就是我想要的。请看需要的situation@Zydnar:仅当
OPR
GDP
不在字符串末尾时,我才需要拆分。这是0和1的情况,2和3的情况是和,不需要分割。我如何在数据帧中使用它?示例仅为4行,但实际数据位于从csv文件导入的大型数据框中。如何将其用于熊猫数据框?示例只有4行,但实际数据位于从csv文件导入的大型数据框中。为避免误解,这里有更多的列。我刚刚创建了一个简单的示例。我使用pd阅读csv。read_cvs(fileName,delimiter=“;”)您已经掌握的两个答案是否为您提供了足够的示例或解决问题的思路,以便您可以结束问题并着手解决问题?我理解示例,但不理解如何使用数据帧而不是列表来实现这一点。我可能没有看到这种联系,很抱歉,你的问题是如何使用正则表达式分解字符串。这两个答案都是这样的。如果您现在有一个关于如何将列表转换为数据帧的问题,那么这是一个不同的问题,应该作为一个新问题来提问。但是,您是否尝试在此处查看:
http://pbpython.com/pandas-list-dict.html
我认为很明显,这与我在问题(以及标签)中提到的熊猫和数据帧有关。我还发布了一些我已经尝试过的与熊猫相关的代码。我不想从列表中读取数据,也不想从数据帧中读取数据。使用Pandas.read_csv导入数据。所以我已经有了一个DataFrame,希望将字符串从一列分解为两列。很抱歉,误解了,但是还有更多的列。我刚刚创建了一个简单的示例。我使用pd.read_cvs(fileName,delimiter=“;”)阅读csv。您已经给出的两个答案是否为您提供了足够的示例或解决问题的思路,以便您可以结束问题并着手解决问题?我在下面