拆分字符串无分隔符,具有限制的字段名称和内容

Posted

技术标签:

【中文标题】拆分字符串无分隔符,具有限制的字段名称和内容【英文标题】:split string no delimiter with limitative field names and content 【发布时间】:2020-03-20 11:14:11 【问题描述】:

我有一个带有 bankmutations 的数据框。 数据框包含一个描述列。在此列中,有限制性的字段名称及其内容。 它看起来像:

AAm.loc[0, ’OmsBank'] => ‘  fieldname1: content fn1   fieldname3: content fn3     ‘
AAm.loc[1, ’OmsBank'] => ‘  fieldname5: content fn5   fieldname2: content fn2     ‘

如果有解决这个问题的一般方法(分解字段名和内容中的长字符串),我做了很多谷歌搜索。到目前为止,还没有找到简单的解决方案。

我可以使用双空格作为分隔符来分割,但在字段内容内也有双空格。所以这不是一个有效的选择。尝试将 split 与列表/数组一起使用,但也没有运气。

到目前为止,我已经创建了一个小的第二个数据框,其中包含限制性字段名、字段名的起始位置、内容的起始位置和内容的结束位置。

我遍历银行对账单的行,检查存在哪些字段名,并将开始标签的位置和开始内容存储在小数据框中 我按字段名的位置对小数据框进行排序,重置索引,然后我可以确定内容的结束位置(下一个字段名的开始)。 最后一个字段名没有下一个字段名。所以我必须将描述字符串的长度存储为结束值。 然后我可以将特定元素的内容存储在银行对帐单数据框中。

我觉得它可以做得更“pythonic”和高效,vectorise,lambda函数? 如果有人有建议,我将不胜感激。这个问题的一般解决方案也可以帮助其他人。

到目前为止我的代码:

import pandas as pd
# data
tosplit = ['SEPA Inc dl Incassant: blabla  Naam: Insurance    Machtiging: number  Omschrijving: Rel.nr. number2    IBAN: iban#', 
          'SEPA Overboeking  IBAN: iban#  BIC: bic#  Naam: blabla  Omschrijving: Refund  Kenmerk: refcode', 
          'SEPA iDEAL  IBAN: iban#  BIC: bic#  Naam: seller  Omschrijving: description  double space  Kenmerk: refcode',
          'SEPA iDEAL  IBAN: iban#  BIC: bic#  Naam: city  Omschrijving: citytax']
AAm = pd.DataFrame(tosplit, columns= ['OmsBank'])
AAm['Naam'] = ''
AAm['Oms'] = ''
AAm
# field list
fld = [' IBAN: ', ' BIC: ', ' Naam: ', ' Omschrijving: ', ' Kenmerk: ', ' Referentie: ', ' Machtiging: ', ' Incassant: ']
fld.sort()

# store field list in dataframe and add columns for position
fld= pd.DataFrame(fld, columns = ['fldnm'] )
ser= [0]*len(fld)
fld = fld.assign(bgn = ser, bgc = ser, end = ser )
# loop through AAm (dataframe with bankmutations) and proces data
for i in AAm.index:

    # search for fieldnames and store postion (begin of fieldname and begin of fieldcontent) if the are found
    for j in fld.index:
        temp = AAm.loc[i, 'OmsBank'].find(fld.loc[j,'fldnm'])
        if temp == -1: 
            temp2 = -1 
        else:
            temp2 = temp+len(fld.loc[j,'fldnm'])
            fld.loc[j,'bgn'] = temp
            fld.loc[j,'bgc'] = temp2

    # order by postion and reset index
    fld = fld.sort_values(by ='bgc')
    fld.reset_index(drop=True, inplace = True)
    # establish end of content position. For the last one it is length general string
    for j in fld.index:
        if (fld.loc[j, 'bgn']>0) & (j < len(fld)-1):
            fld.loc[j, 'end'] = fld.loc[(j+1), 'bgn']
        fld.loc[len(fld)-1, 'end'] = len(AAm.loc[i, 'OmsBank'])

    # store start/end of relevant field content in AAm
    nm_om = fld[(fld['fldnm'] == ' Naam: ') | (fld['fldnm'] == ' Omschrijving: ')]
    nm_om.reset_index(drop=True, inplace = True)
    AAm.loc[i,'Naam'] = AAm.loc[i,'OmsBank'][nm_om.loc[0, 'bgc']:nm_om.loc[0, 'end']].strip()
    AAm.loc[i,'Oms'] = AAm.loc[i,'OmsBank'][nm_om.loc[1, 'bgc']:nm_om.loc[1, 'end']].strip()

    #reset values in fieldlist
    fld[['bgn', 'bgc', 'end']]=0

【问题讨论】:

解决(更复杂的)问题的最佳实践是提供所谓的“可重现”场景,人们可以在他们的 IDE 中复制和粘贴您的数据框 + 代码并遇到相同的问题。对你来说,这意味着包含一个带有pd.DataFrame 的数据集,这样人们就可以立即以正确的格式获取数据,因为这对你的问题非常重要。例如,请参阅我的 questions 之一 @Erfan:这是一个相当大的集合。我的代码有效,但我认为它远非最佳。我将尝试添加一个小数据框以使其可重现 是的,我们的想法是将您的问题分解为一个小的示例数据集,而不是包含整个数据集。我也会把你的问题分解成小部分,现在你发布了你的整个代码,这会吓跑大多数人,因为他们不想通过 80 行代码来调试。 您提供了 2 行的描述。生成数据帧提取的一种简单方法是 df.iloc[:10].to_dict(orient='list'):它提供前 10 行的可复制粘贴内容(将切片调整为相关的内容) 【参考方案1】:

我发现了我的问题并发现了正则表达式。您可以搜索所有类型的(文本)模式。我的模式是'字段名:字段值 secondfieldname:第二个字段值'。 您可以将这些块放在括号中并使用 group(number) 引用它们,其中 0 是整个搜索字符串,1 是第一组等。

其中一个示例行是:

tosplit = 'SEPA Inc dl Incassant: blabla  Naam: Insurance    Machtiging: number  Omschrijving: Rel.nr. number2    IBAN: iban#'

导入正则表达式并搜索字符串中的模式进行拆分,并使用括号将它们分组:

import re    
splitted = re.search(r'( Naam: )(.*)( Machtiging: )', tosplit)

名称内容可以通过

轻松获取
name = splitted.group(2)

【讨论】:

以上是关于拆分字符串无分隔符,具有限制的字段名称和内容的主要内容,如果未能解决你的问题,请参考以下文章

SQL server拆分字段的SQL语句

如何使用 sql (access) 将数字列(字段名)拆分为 2 列

更改用于分隔具有相同名称标识符的表单输入字段的字符?

oracle 如何将一个字段里的值拆分为多个值显示出来

将分隔字段转换为具有名称和值的行

Hibernate给表和字段设置前后缀及分隔符