【问题标题】:Search for numeric and alphanumeric post codes in addresses在地址中搜索数字和字母数字邮政编码
【发布时间】:2021-04-25 20:59:40
【问题描述】:

我有一个看起来像这样的熊猫数据框:

Name       Address
Alan       23 Belby road, home near me 71234
Tom        PA23 6NH brickby avenue
Solty      7 solty road 7123-234
Ben        Nowhere road 713456 Belgium

我想获得带有如下结果数据框的邮政编码:

Name       Address                               Postcode
Alan       23 Belby road, home near me 71234     71234
Tom        PA23 6NH brickby avenue               PA23 6NH
Solty      7 solty road 7123-234                 7123-234
Ben        Nowhere road 713456 Belgium           713456

我看了Python, Regular Expression Postcode searchpython - get zipcode from full address的帖子

不清楚如何进行。

【问题讨论】:

    标签: python-3.x pandas dataframe


    【解决方案1】:

    每个捕获组都可以在由|分隔的re表达式中指定

    Extract all 模式匹配到各个列(请参阅。Multiple Pattern using Regex in Pandas

    然后尝试使用 bfill 将所有匹配项强制到第一列(参见。How to collapse multiple columns into one in pandas

    然后合并回原来的数据集。

    import pandas as pd
    
    postcode_re = r'([Gg][Ii][Rr] 0[Aa]{2})|' \
                  r'((([A-Za-z][0-9]{1,2})|' \
                  r'(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|' \
                  r'(([A-Za-z][0-9][A-Za-z])|' \
                  r'([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\s?[0-9][A-Za-z]{2})|' \
                  r'(\d{5}\-?\d{0,4})|' \
                  r'(\d{4}\-?\d{0,3})'
    
    df = pd.DataFrame({'Name': {0: 'Alan', 1: 'Tom',
                                2: 'Solty', 3: 'Ben',
                                4: 'Mary', 5: 'Mike'},
                       'Address': {0: 'PA23 6NH brickby avenue',
                                   1: '818 mention 560100',
                                   2: 'calculate AB24 EFT',
                                   3: '818 where 560100',
                                   4: 'Nowhere road 713456 Belgium',
                                   5: '7 solty road 7123-234'}})
    
    df = df.merge(df['Address']
                  .str
                  .extractall(postcode_re)
                  .bfill(axis=1)[0]
                  .droplevel(level=1)
                  .rename('Postcode'),
                  left_index=True,
                  right_index=True,
                  how='left')
    
    print(df.to_string())
    

    输出:

        Name                      Address  Postcode
    0   Alan      PA23 6NH brickby avenue  PA23 6NH
    1    Tom           818 mention 560100    560100
    2  Solty           calculate AB24 EFT       NaN
    3    Ben             818 where 560100    560100
    4   Mary  Nowhere road 713456 Belgium    713456
    5   Mike        7 solty road 7123-234  7123-234
    

    如果您需要更多邮政编码正则表达式,请参阅postal-codes

    【讨论】:

    • 你为什么要用.iloc[:, 0]查看所有行和第一列?我的兴趣只在于与特定名称相对应的每一行。
    • 我对您的措辞感到困惑,“我的兴趣只在于与特定名称相对应的每一行”。您的问题是“如何提取数字和字母数字邮政编码有趣的地址”。 Extractall 为每个捕获组生成一个列,如果匹配,则匹配进入相应的列,如果没有匹配,则该列中有一个空值。在这种情况下,extractall 生成的帧是 3 列宽。但是您的示例输出只有 1 个新列“邮政编码”。因此 bfill 和 .iloc[:, 0] 将 3 列包含 null 的列转换为 1 列包含尽可能少的 null。
    • 我之所以这么问,是因为当我在更大的数据集上尝试它时,在 Postcode 列中得到了不正确的结果和大量空值,因此我需要了解幕后发生的事情。
    • 您需要将任何模式添加到您想要匹配的正则表达式中。如果没有匹配,你会得到一个空值。底部有一个按国家/地区分类的邮政编码正则表达式的链接,可能会有所帮助。此外,更具体的模式需要首先出现,因为您只会得到第一个非空值。您也可以将列折叠成可能匹配的列表,这又取决于您尝试匹配的邮政编码类型。
    • 知道了。我最初做了一些错误的假设。我已经更新了实现以使用regex for the whole uk 并修复了其中一些错误假设。从我的简短搜索来看,AB24 EFT 似乎不是有效的邮政编码。对于AB24 组邮政编码,第二组必须以数字开头。这就是您在该列中得到空值的原因。
    猜你喜欢
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 2011-09-11
    相关资源
    最近更新 更多