如何使用不均匀长度的列表项创建pandas数据框列?

3

我有一个地址列表,想把它们放到数据框中,每一行是一个新的地址,列是地址的单位(标题、街道、城市)。

但是,由于列表的结构不同,某些地址比其他地址更长。例如:

address = ['123 Some Street, City','45 Another Place, PO Box 123, City']

我是一个有用的助手,可以为您翻译文本。
我有一个带有以下列的pandas数据框:
Index     Court       Address                              Zipcode   Phone                           
0         Court 1     123 Court Dr, Springfield            12345     11111
1         Court 2     45 Court Pl, PO Box 45, Pawnee       54321     11111
2         Court 3     1725 Slough Ave, Scranton            18503     11111
3         Court 4     101 Court Ter, Unit 321, Eagleton    54322     11111

我希望将地址列根据逗号的数量拆分成最多三列,其中缺失的值用NaN填充。
例如,我希望数据看起来像这样:
Index     Court       Address          Address2     City           Zip  Phone                                          
0         Court 1     123 Court Dr     NaN          Springfield    ...   ...           
1         Court 2     45 Court Pl      PO Box 45    Pawnee         ...   ...
2         Court 3     1725 Slough Ave  NaN          Scranton       ...   ...
3         Court 4     101 Court Ter    Unit 321     Eagleton       ...   ...

我已经在StackOverflow上尝试了许多不同的解决方案,但都没有成功。最接近成功的代码如下:
df2 = pd.concat([df, df['Address'].str.split(', ', expand=True)], axis=1)

但是这将返回一个数据帧,它会添加以下三列到结尾,结构如下:
...  0              1             2
... 123 Court Dr   Springfield   None
... 45 Court Pl    PO Box 45     Pawnee

这很接近理想,但是你可以看到对于较短的条目,城市与较长的条目的第二个地址行对齐。
理想情况下,第二列应该在每一行都填写城市,而第一列应该在适用时交替显示“None”和第二个地址行。
希望我表达清楚了,这是一个比较棘手的问题。谢谢!
3个回答

0

地址,特别是由人工输入产生的地址可能会很棘手。但是,如果您的地址只符合这两种格式,那么这将起作用:

注意:如果还有其他格式需要考虑,这将打印出问题所在。

def split_address(df):
    for index,row in df.iterrows():
        full_address = df['address']
        if full_address.count(',') == 3:
            split = full_address.split(',')
            row['address_1'] = split[0]
            row['address_2'] = split[1]
            row['city'] = split[2]
        else if full_address.count(',') == 2:
            split = full_address.split(',')
            row['address_1'] = split[0]
            row['city'] = split[1]
        else:
            print("address does not fit known formats {0}".format(full_address))

基本上有两个东西可以帮助你,一个是 string.count() 函数,它可以告诉你字符串中逗号的数量,另一个是你已经发现的 string.split() 函数,它可以将输入分割成数组。你可以引用这个数组的部分来将每一部分分配到正确的列中。

0
你可以像这样做:
df['Address1'] = df['Address'].str.split(',').str[0]
df['Address2'] = df['Address'].str.extract(',(.*),')
df['City'] = df['Address'].str.split(',').str[-1]

0

你可以尝试使用 usaddress 包来创建一个函数。当我需要将地址拆分成各个部分时,它对我非常有帮助:

import usaddress

df = pd.DataFrame(['123 Main St. Suite 100 Chicago, IL', '123 Main St. PO Box 100 Chicago, IL'], columns=['Address'])

然后创建函数来定义您想要如何拆分数据:

def Address1(x):
    try:
        data = usaddress.tag(x)
        if 'AddressNumber' in data[0].keys() and 'StreetName' in data[0].keys() and 'StreetNamePostType' in data[0].keys():
            return data[0]['AddressNumber'] + ' ' + data[0]['StreetName'] + ' ' + data[0]['StreetNamePostType']
    except:
        pass

def Address2(x):
    try:
        data = usaddress.tag(x)
        if 'OccupancyType' in data[0].keys() and 'OccupancyIdentifier' in data[0].keys():
            return data[0]['OccupancyType'] + ' ' + data[0]['OccupancyIdentifier']
        elif 'USPSBoxType' in data[0].keys() and 'USPSBoxID' in data[0].keys():
            return data[0]['USPSBoxType'] + ' ' + data[0]['USPSBoxID']
    except:
        pass

def PlaceName(x):
    try:
        data = usaddress.tag(x)
        if 'PlaceName' in data[0].keys():
            return data[0]['PlaceName']
    except:
        pass

df['Address1'] = df.apply(lambda x: Address1(x['Address']), axis=1)
df['Address2'] = df.apply(lambda x: Address2(x['Address']), axis=1)
df['City'] = df.apply(lambda x: PlaceName(x['Address']), axis=1)

输出:

                               Address      Address1    Address2     City
0   123 Main St. Suite 100 Chicago, IL  123 Main St.   Suite 100  Chicago
1  123 Main St. PO Box 100 Chicago, IL  123 Main St.  PO Box 100  Chicago

感谢大家的回复! - n0ro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接