pandas 拆分框架柱

ftf50wuq  于 2023-10-14  发布在  其他
关注(0)|答案(3)|浏览(100)

我有不同地址的 Dataframe 。
| 地址|
| --|
| 美国,犹他州,里奇菲尔德,315 E栋|
| 俄罗斯,莫斯科州,莫斯科,阿尔巴特区,新街,78号楼|
我必须将列'Address'拆分为多个列,以便每个行元素都在正确的列中:
| 国家|地区/国家|市|区|街|建筑|
| --|--|--|--|--|--|
| 美国|犹他州|里奇菲尔德|NA| NA| 315 E号楼|
| 俄罗斯|莫斯科州|莫斯科|阿尔巴特区|新街|78号楼|
你能帮忙吗?

yacmzcpb

yacmzcpb1#

另一种方法是使用None值创建列表

import pandas as pd

columns_order = ['Country', 'Region/State', 'City', 'District', 'Street', 'Building']
df = pd.DataFrame({'Address': datas})

def split_address(address):
    parts = address.split(', ')
    num_nones = len(columns_order) - len(parts)
    ordered_parts = parts + [None] * num_nones

    return pd.Series(ordered_parts, index=columns_order)

res = df['Address'].apply(split_address)
eulz3vhy

eulz3vhy2#

import pandas as pd

# Minimal reproducible example (that the way you should have given it, fyi :))
df=pd.DataFrame({'Address': ['USA, Utah, Richfield, building 315E', 'Russia, Moscow oblast, Moscow, Arbat District, New street, building 78']})

# Easy part, get country, region, city
splitAddress = df['Address'].str.split(',')
df[['Country', 'Region', 'City']] = splitAddress.str[:3].tolist()
rest = splitAddress.str[3:]

# District, if there is one, should be in first item of unused elements
m=(rest.str.len()>0) & (rest.str[0].str.contains('District'))
df.loc[m, 'District'] = rest[m].str[0]
rest[m]=rest[m].str[1:]

# Street, if there is one, should be the first remaining
m=(rest.str.len()>0) & (rest.str[0].str.contains('street'))
df.loc[m, 'Street'] = rest[m].str[0]
rest[m]=rest[m].str[1:]

# What remains is the rest of address
# WE could just assume that there is only one field left (at most) as in your example. But just in case, rejoin rest
m=rest.str.len()>0
df.loc[m, 'Building'] = rest[m].str.join(', ')

我认为需要进行一些调整。我对什么是地区(包含单词“District”的部分,区分大小写,没有其他内容)、街道(包含单词“street”的部分,区分大小写,没有其他内容)和建筑物(既不是地区也不是街道)的检测可能需要一些更精细的测试。但从你给出的极少数迹象来看...另外,从那里你应该能够添加标准。
此外,一般来说,splitexpand=True参数(在一个简短的回答中使用过,现在已经消失了)可能是将字符串拆分为列的更好方法。我没有使用它,因为我不知道如何只保留3,然后,如何用它来做我的“过滤rest的第一个元素,删除我使用的”部分。但也许有一种方法(我不是一个“Pandas大师”,所以有很多一行代码,我在几行代码)。但是,好吧,关键是,我没有任何for,也没有任何apply,也没有任何使迭代成为纯Python的一部分的东西。因此,即使可能有一些更快的解决方案(甚至可能快两倍或3倍),它们也应该处于相同的速度数量级(与我们在删除for或一些apply/map时所经历的×1000因子完全不同)

ckocjqey

ckocjqey3#

你可以试试regex:

import re

pat = (r'(?P<Country>[^,]+),\s*'
       r'(?P<State>[^,]+),\s*'
       r'(?P<City>[^,]+)'
       r'(?:,\s*(?P<District>.*district[^,]*))?'
       r'(?:,\s*(?P<Street>.*street[^,]*))?'
       r'(?:,\s*(?P<Building>.*building.*))?')
ADDRESS = re.compile(pat, re.IGNORECASE)
out = df['Address'].str.extract(ADDRESS)

输出量:

>>> out
  Country          State       City        District      Street       Building
0     USA           Utah  Richfield             NaN         NaN  building 315E
1  Russia  Moscow oblast     Moscow  Arbat District  New street    building 78

Regex101上的演示

相关问题