Python 重写一个提取字符串中行政区划的 Series(上)
创作背景
本菜鸡最近在数据分析时遇到这样一列数据,如图
我想进行的操作是:
- 提取其中
各行政区划及名称
。eg: 江苏省,北京市 这种。详见本文。 - 像
pd.to_datetime()
后可以调用time_series.dt.year
返回对应的年序列
一样,我的area_series
可以返回对应的 省,市,市辖区/县。详见文章。 - 注:本文将 市辖区 和 县 认为是 平级,便于数据提取,如有不妥请指正。
如果觉得我这篇文章写的好的话,能不能给我 点个赞 ,评论 一波。
如果要点个 关注 的话也不是不可以🤗
思路分析 - 提取行政区划
首先,我们得提取字符串中的 行政区划,怎么提取呢?当然是用 re
了!
分析一下字符串(以 福建省莆田市城厢区 、 新疆维吾尔自治区乌鲁木齐市 和 青海省共和县 为例)。
eg1:福建省莆田市城厢区
这个好分析
- 省级行政区 是
福建省
。 - 市级行政区 是
莆田市
。 - 市辖区 是
城厢区
。
那我们就可以这样写正则表达式
(\S+省)(\S+市)(\S+区)
测试一下
可以看到,都提取出来了,但是,我们要的数据在一个 list
里的一个 tuple
元素中,不利于后期处理,所以我们修改一下。
修改后的正则表达式:
\S+省|\S+市|\S+区
再看一下效果:
这时候我们要的数据就在一个 list
里了。
eg2:新疆维吾尔自治区乌鲁木齐市
这个字符串中:
- 省级行政区 是
新疆维吾尔自治区
。 - 市级行政区 是
乌鲁木齐市
。 没有
县级行政区。
仿照上边的,我们可以这样写正则表达式:
\S+自治区|\S+市
看一下结果:
eg3:青海省共和县
我们可以看出:
- 省级行政区 是
青海省
。 没有
市级行政区。- 县级行政区 是
共和县
。 - 注:目测是 县级行政区,此处 仅供举例说明,如有更改请指出。
那我们就这样写正则表达式:
\S+省|\S+县
看一下结果:
泛化
从上述三个例子可以看出,我们可以使用 \S+【行政区划】
即可提取到对应的 行政区划及其名称 。
但是有个问题,上述三个正则表达式 泛化能力不强,要不然怎么需要 三
个正则表达式而不是 一个
才能提取到我们想要的结果。
那我们现在就要写一个 泛化能力强 的正则表达式,能够匹配这个地点序列中所有的字符串。
分析可得,地名都是由 【省级行政区】【市级行政区】【市辖区 / 县级行政区】 组成。
其中:
- 省级行政区 包括 省,自治区。
- 市级行政区 包括 市,旗。
- 市辖区 / 县级行政区 包括 区,县。
我们可以这样写:
\S+省|\S+自治区|\S+市|\S+旗|\S+区|\S+县
可是这又带来两个问题:
- 各级行政区后缀名 名称不止我列举的这些,还可能有其他的,要新增到正则表达式的话有些麻烦。
- 提取出来的结果无法分辨出相应的行政区划。
怎么解决呢?
我的思路是:
- 创建一个 行政区划列表,固定包含 三 个元素。
- 每个元素是 list,包含 该等级行政区划的后缀名。
- 拼接正则表达式。
代码如下
divisions = {
'province': ['省', '自治区'],
'city': ['市'],
'county': ['区', '县', '旗']
}
# 正则表达式 '\S+省|\S+自治区|\S+市|\S+旗|\S+区|\S+县'
re.findall('|'.join(['|'.join(['\S+' + char for char in chars]) for chars in divisions.values()]), '【要提取的字符串】')
测试一下:
- 福建省莆田市城厢区
- 新疆维吾尔自治区乌鲁木齐市
- 青海省共和县
看起来效果还不错,相对来说还是有 一定的泛化能力。
为了方便后边的数据处理,我们规定一下输出格式:
['【省】', '【市】', '【市辖区 / 县】']
代码如下:
def check_exist(area, names):
for name in names:
if name in area:
return area
else:
return ''
divisions = {
'province': ['省', '自治区'],
'city': ['市'],
'county': ['区', '县', '旗']
}
# 提取结果列表
result = re.findall('|'.join(['|'.join(['\S+' + char for char in chars]) for chars in divisions.values()]), '【要提取的字符串】')
# 手动设置索引
count = 0
# 结果列表
result_list = []
# 遍历行政区划列表,保证结果列表长度与其相等
for key in divisions:
# 如果索引小于提取结果长度
if count != len(result):
# 查看是否属于 key 这个行政区划
test_exist = check_exist(result[count], divisions[key])
# 如果属于本行政区划,加入结果列表
result_list.append(test_exist)
if test_exist:
count += 1
else:
# 提取结果遍历完但行政区划列表还未遍历完,说明后边的行政区划都没有,就加入空字符
result_list.append('')
print(result_list)
测试一下:
成功完成任务!!!
结尾
有想要一起学习 python
的小伙伴可以 私信我
进群哦。
以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。