【问题标题】:Compare values between 2 dataframes and transform data比较 2 个数据帧之间的值并转换数据
【发布时间】:2021-10-03 05:28:25
【问题描述】:

此脚本的主要目的是将 csv 中存在的数据的正则表达式格式与该国家/地区的官方邮政编码正则表达式格式进行比较,如果格式不匹配,脚本将对所述数据进行转换并将其全部输出到一个最终数据帧中。

我有 2 个 csv 文件,一个 (countries.csv) 包含以下列和数据示例

输入:

Contact ID Country Zip Code
1 USA 71293
2 Italy IT 2310219

和另一个带有以下数据示例的 csv (Regex.csv):

Country Regex format
USA [0-9]{5}(?:-[0-9]{4})?
Italy \d{5}

现在,第一个 csv 有大约 35k 条记录,所以我想创建一个函数,该函数循环通过 regex.csv(Dataframe)来获取国家列和正则表达式格式。然后它会遍历国家列表以获取 regex['country'] == countries['country'] 的每个实例,并将正则表达式转换应用于该国家/地区的邮政编码。

到目前为止,我有这个功能,但我无法让它工作。

def REGI (dframe):
    dframe=pd.DataFrame().reindex_like(contacts)
    cols = list(contacts.columns)
    
    for index,row in mergeOne.iterrows():
        country = (row['Country'])
        reg = (row[r'regex'])
        
        for i, r in contactsS.iterrows():
            if (r['Country of Residence'] == country or r['Country of Residence.1'] == country or r['Mailing Country (text only)'] == country or r['Other Country (text only)'] == country) :
                dframe.loc[i] = r
                
        dframe['Mailing Zip/Postal Code']=dframe['Mailing Zip/Postal Code'].apply(str).str.extractall(reg).unstack().apply(lambda x:','.join(x.dropna()), axis=1)
    contacts.loc[contacts['Contact ID'].isin(dframe['Contact ID']),cols] = dframe[cols]
    dframe = dframe.dropna(how='all')
    
    return dframe

['Contact ID'] 被用作标识符列。

第二个 for 循环独立工作,但我需要手动重新输入新的数据框名称、正则表达式格式和国家名称(没有第一个 for 循环)。

目前我收到以下错误: ValueError ValueError:模式不包含捕获组


删除了一些列以模仿上面给出的示例 dataframes & error error continued

如果我将结果粘贴到新的数据框中,它会返回以下内容: results in a new dataframe


文本示例

Account ID Country Zip/Postal Code
1 United Kingdom WV9 5BT
2 Ireland D24 EO29
3 Latvia 1009
4 United Kingdom EN6 1JE
5 Italy 22010

正则表达式表

Country Regex
United Kingdom ([Gg][Ii][Rr] 0[Aa]{2}) (([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2}) ([A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2})
Latvia [L]{1}[V]{1}-{4}
Ireland STRNG_LTN_EXT_255
Italy \d{5}

英国正则表达式:

([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za -z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|( [A-Za-z][A-Ha-hJ-Yj-y][0-9]?[A-Za-z])))) [0-9][A-Za-z]{2} )

【问题讨论】:

  • 这里的目标是什么?确保邮政编码与每个国家/地区的模板匹配?例如,意大利不会因为领先的“IT”而匹配?
  • @mozway 的目标是找到邮政编码不正确的正则表达式格式的地方,如果格式不正确,则脚本会将该行的邮政编码更改为匹配正确的格式。如果它已经是正确的格式,它将保持原样。
  • @mozway 我已经尝试过你的解决方案,但是我收到了这个错误 ValueError: Wrong number of items passed 10, placement means 1
  • 请给出完整的数据集。该示例运行良好。
  • @mozway 其中一个数据集只有国家列表和正则表达式格式(2 列),另一个数据集有联系信息(姓名、ID、地址 1、2、3、国家和邮政编码等)(11 列)。

标签: python regex pandas csv formatting


【解决方案1】:

根据您对我的评论的回复,我建议使用您的正则表达式直接修复邮政编码:

df3 = df2.set_index('Country')

df1['corrected_Zip'] = (df1.groupby('Country')
                           ['Zip Code']
                           .apply(lambda x: x.str.extract('(%s)' % df3.loc[x.name, 'Regex format']))
                        )
df1

按国家分组,应用该国家的正则表达式,并提取值。

输出:

   Contact ID Country    Zip Code corrected_Zip
0           1     USA       71293         71293
1           2   Italy  IT 2310219         23102

注意。如果你愿意,你可以直接覆盖Zip Code df1['Zip Code'] = …

NB2。这只有在所有国家/地区都有 df2 的条目时才有效,如果不是这种情况,您需要为此添加一个检查(让我知道)

NB3。如果您想知道哪些行的 zip 无效,可以使用以下方法获取它们:

df1[df1['Zip Code']!=df1['corrected_Zip']]

【讨论】:

    猜你喜欢
    • 2018-09-27
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 2019-01-02
    • 2022-01-15
    相关资源
    最近更新 更多