【发布时间】: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 行的可复制粘贴内容(将切片调整为相关的内容)