在有条件的第一个数字后拆分列

时间:2019-11-07 21:46:01

标签: python pandas

我有一个保存地址的数据框,该地址分为多列:

address        postalcode      city       province       country
-----------------------------------------------------------------
123 Fake St     F1A2K3       Fakeville      ON              CA

我想将地址栏分为两个单独的栏,一栏用于门牌号码,一栏用于街道名称。因此,运行它之后,上面的df将如下所示:

house_no    street        postalcode      city       province       country
----------------------------------------------------------------------------
  123       Fake St        F1A2K3       Fakeville      ON              CA

我一直在通过简单地使用df[['house_no', 'street']] = df['address'].str.split(' ', 1, expand=True)来做到这一点,直到发现address列下的某些地址被构造为Apt 316 555 Fake Drive(或Unit 316 555 Fake Drive )。因此,当我在这些上运行当前使用的内容时,我得到:

house_no          street        postalcode      city       province       country
---------------------------------------------------------------------------------
  Apt       316 555 Fake Drive     F1A2K3       Fakeville      ON           CA

显然,这不是我想要的。

因此,从本质上讲,我需要一种算法,该算法会在第一个数字之后拆分字符串,除非它以“ Unit”或“ Apt”开头,在这种情况下,它将采用它看到的第二个数字并将其拆分为{{ 1}}列。

我需要在不丢失任何信息的情况下执行此操作,因此也要保留单位/公寓号(可以存储在house_no列中,但理想情况下将拥有自己的house_no列)。因此,理想情况下,输出应如下所示:

unit_no

鉴于原来的unit_no house_no street postalcode city province country --------------------------------------------------------------------------------- Apt 316 555 Fake Drive F1A2K3 Fakeville ON CA 列包含address,现在又分为Apt 316 555 Fake Driveunit_nohouse_no

我不确定从哪里开始,所以将不胜感激。

4 个答案:

答案 0 :(得分:1)

让我们尝试以下数据:

df = pd.DataFrame({'address':['123 Fake Street', 'Apt 316 555 Fake Drive']})

# df
#                   address
# 0         123 Fake Street
# 1  Apt 316 555 Fake Drive

由于您未指定是否要捕获Unit\Apt号,因此我认为您不会:

df.address.str.extract('(?:Unit|Apt \d+ )?(?P<house_no>\d+) (?P<street>.*)$')

输出:

  house_no       street
0      123  Fake Street
1      555   Fake Drive

如果要保留Unit/Apt,仅需进行一些修改:

df.address.str.extract('(?P<unit_no>Unit|Apt \d+ )?(?P<house_no>\d+) (?P<street>.*)$')

输出:

    unit_no house_no       street
0       NaN      123  Fake Street
1  Apt 316       555   Fake Drive

答案 1 :(得分:0)

您可以使用df.loc函数,这应该可以工作。

df.loc[~df['address'].str.contains('Unit|Apt'), 'house_no'] = df['address'].str.split(' ')

答案 2 :(得分:0)

如果您总是有一个数字,后跟一个空格,然后是街道名称,则可以使用str.split('') 对地址中的数据起作用

例如,使用街道名称创建新列,使用街道编号创建新列

使用以下命令创建两个数组,其中一个带有街道编号 数字= address.split('')

数字[0]将始终是街道号码

由于某些街​​道名称带有空格,因此请在数字后附加数字[1:],这就是街道名称列的数据

很抱歉输入伪代码。

答案 3 :(得分:0)

我不确定我是否理解这个问题,但是如果您想消除单词Apt或Unit,那么可以做到这一点(这里df和df2是我制作的两个.xlsx文件,而df2只是另一个包含您所访问的列的数据框需要(house_no和street),并且具有与df一样多的行,但具有空值):

import pandas as pd

df=pd.read_excel('raspuns_so.xlsx')

df2=pd.read_excel('sol.xlsx')
tmp=df['add'].str.split(' ', 1, expand=True)
for i, row_series in df2.iterrows():
    if tmp[0][i].isdigit():
        df2[['house_no', 'street']] = df['add'].str.split(' ', 1, expand=True)
    else:
        var=tmp[1][i].split(' ')
        arr=[var[0],var[1]]
        df2.at[i,'house_no'] = " ".join(arr)
        df2.at[i,'street'] = var[2]
print df2

我的df:

              address      pc       city province country
0         123 Fake ST  F1A2K3  Fakeville       ON      CA
1  Apt 123 555 FakeST  300000  Fakeville      OFF     USA

我的df2:

   house_no  street  pc  city  province  country
0         0       0   0     0         0        0
1         0       0   0     0         0        0
我运行代码后的

df2:

  house_no   street  pc  city  province  country
0      123  Fake ST   0     0         0        0
1  123 555   FakeST   0     0         0        0