使用python提取中文地址描述中的省市区信息
引言
在一次建模比赛中,我手头里的原始数据中有一个“地址描述”地段,如下:
地址描述 |
---|
广州国际采购中心1401 |
上海市长宁区金钟路658弄5号楼5楼 |
徐汇区虹漕路461号58号楼5楼 |
济南市历下区和平路34号轻骑院内东二层山东朵拉 |
这样的地址描述字段过于随意,很难使用,但是看这些字符串的样子似乎又可以提取出其所在的省、市和区,即使只能够提取出区或者市,如果我们有一个省、市和区的归属数据库的话,应该也能够将剩下的信息映射出来,如果自己写的话肯定很麻烦,还要去网上找数据库,其实python中已经有一个现成的模块可以用,一条命令就可以将上面的“地址描述”字段转换成如下的样子:
省 | 市 | 区 |
---|---|---|
广东省 | 广州市 | |
上海市 | 上海市 | 长宁区 |
上海市 | 上海市 | 徐汇区 |
山东省 | 济南市 | 历下区 |
模块安装
目前支持python3
pip install chinese_province_city_area_mapper
官方文档地址
https://pypi.python.org/pypi/chinese_province_city_area_mapper
项目的Github地址:https://github.com/DQinYuan/chinese_province_city_area_mapper
基本功能
这个模块中最主要的类是chinese_province_city_area_mapper.transformer.CPCATransformer(注:CPCA是Chinese Province City Area的缩写),该类的transform方法可以输入任意的可迭代类型(如list,Series等),然后将其转换为一个DataFrame,示例代码如下:
location_str = ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区", "朝阳区北苑华贸城"]
from chinese_province_city_area_mapper.transformer import CPCATransformer
cpca = CPCATransformer()
df = cpca.transform(location_str)
df
输出的结果为:
区 市 省
0 徐汇区 上海市 上海市
1 洛江区 泉州市 福建省
2 朝阳区
从上面的程序输出中你会发现朝阳区并没有被映射到北京市,这是因为在中国有多个同名的叫做朝阳区的区,并且他们位于不同的市,所以程序就不知道该映射到哪一个市了,因此就不对其进行映射,如果你确定你的数据中的朝阳区都是指北京市的那个朝阳区的话,可以在CPCATransformer的构造函数中传一个字典(叫做umap参数,是user map的简称),指定朝阳区都要映射到北京市,注意只有区到市的这一级映射存在重名问题,中国的市的名称都是唯一的,省的名称也都是唯一的,示例代码如下:
location_str = ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区", "朝阳区北苑华贸城"]
from chinese_province_city_area_mapper.transformer import CPCATransformer
cpca = CPCATransformer({"朝阳区":"北京市"})
df = cpca.transform(location_str)
df
输出结果为:
区 市 省
0 徐汇区 上海市 上海市
1 洛江区 泉州市 福建省
2 朝阳区 北京市 北京市
模块中还内置了一个作者推荐大家使用的umap,这个umap中作者根据处理地址数据的经验将那些重名的区映射到了它最常见的一个市,这个umap位于chinese_province_city_area_mapper.myumap.umap,使用如下:
location_str = ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区", "朝阳区北苑华贸城"]
from chinese_province_city_area_mapper.transformer import CPCATransformer
from chinese_province_city_area_mapper import myumap
print(myumap.umap) #查看这个umap的内容
cpca = CPCATransformer(myumap.umap)
df = cpca.transform(location_str)
df
输出和上一个程序一样
地图绘制
模块还可以对上面提取的结果进行地图绘制,依靠的是模块自带的全国省市区经纬度。代码如下:
from chinese_province_city_area_mapper import drawers
#df为上一段代码输出的df
drawers.draw_locations(df, "df.html")
绘制出的地图如下:
地图绘制
数据接口
模块内置了丰富的地理信息数据,如果你只是想用这个模块中的数据的话,模块也提供了相应的接口,如下:
from chinese_province_city_area_mapper.infrastructure import SuperMap
#地区到市的映射数据库,是一个字典类型(key为区名,value为其所属的市名),注意其中包含重复的区名
SuperMap.area_city_mapper
#重复的区名列表,列表类型,如果区名在这个列表中,则area_city_mapper的映射是不准确的
SuperMap.rep_areas
#市到省的映射数据库,字典类型(key为市的名称,value为省的名称)
SuperMap.city_province_mapper
#全国省市区的经纬度数据库,字典类型(key为"省,市,区",value为(维度,经度))
SuperMap.lat_lon_mapper
#获取北京市朝阳区的经纬度
SuperMap.lat_lon_mapper.get("北京市,北京市,朝阳区")
测试数据
作者在这个模块的github库中还提供了一份测试数据,地址如下:
https://github.com/DQinYuan/chinese_province_city_area_mapper/blob/master/addr.csv
里面包含一万多条地址描述信息,将这个数据下载下来可以通过如下代码来测试该模块:
#读取数据
import pandas as pd
origin = pd.read_csv("addr.csv")
#转换
from chinese_province_city_area_mapper.transformer import CPCATransformer
from chinese_province_city_area_mapper import myumap
cpca = CPCATransformer(myumap.umap)
addr_df = cpca.transform(origin["原始地址"])
#输出
processed = pd.concat([origin, addr_df], axis=1)
processed.to_csv("processed.csv", index=False, encoding="utf-8")
输出的processed.csv的前几行如下:
原始地址 | 省 | 市 | 区 |
---|---|---|---|
北京市海淀区北西环西路66号中国技术交易大厦B座1728 | 北京市 | 北京市 | 海淀区 |
广州国际采购中心1401 | 广东省 | 广州市 | |
深圳市南山区东滨路86号B栋第一商务中心2楼 | 广东省 | 深圳市 | 南山区 |
上海徐汇区天钥桥路408号北楼703 | 上海市 | 上海市 | 徐汇区 |
然后再尝试着用如下代码绘图:
from chinese_province_city_area_mapper import drawers
#df为上一段代码输出的df
drawers.draw_locations(processed, "processed.html")
绘制出的图片如下(用浏览器打开processed.html,可能速度会比较慢,要多等待一会):
地图绘制其他细节
关于匹配和映射的更多细节见上面给出的模块的github地址