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