最近要做一个中国地图,以前用pyecharts,最近接触了geopandas 觉得很强大,改用geopandas作图。比如我制作一个疫情分布地图,效果应该是这样的。最终效果。
首先导入需要用的库:
import pandas as pd import matplotlib.pyplot as plt import requests import geopandas as gpd plt.rcParams['font.family'] = 'SimHei'
然后使用爬虫把疫情数据怕取下来,我使用的是 手机端的网易数据接口,地址是,
实时更新|新冠肺炎疫情动态地图https://wp.m.163.com/163/page/news/virus_report/index.html用浏览器打开是这样的。
打开检查工具,找到XHR,看请求的内容。
第一个地址就是,
可以看一下它的相应,
是json数据,没有问题,还是选择用curl工具生成,直接生成的代码是这样的。
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Origin': 'https://wp.m.163.com',
'Connection': 'keep-alive',
'Referer': 'https://wp.m.163.com/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'TE': 'trailers',
}
params = (
('t', '326609897543'),
)
response = requests.get('https://c.m.163.com/ug/api/wuhan/app/data/list-total', headers=headers, params=params)
然后就是数据提取。
使用这个网站,解析一下json数据。
这个网站对json的解析比较鲁棒。
可以看到,我们需要省:每个省的确诊数。
接下来,代码提取。
rj = response.json() rj.keys() rj data = rj['data'] data.keys() areaTree = data['areaTree'] areaTree.keys() chinaData = areaTree[2] chinaData.keys() children = chinaData['children'] len(children) #用一个试试 c1 = children[0] c1.keys() c1['name'] prov = [c['name'] for c in children] print(prov) c1['total']['/confirm/i'] confirm = [c['total']['/confirm/i'] for c in children] print(/confirm/i)
做成一个dataframe,以便后面使用
china_prov = pd.Dataframe({
"prov":prov,
"/confirm/i":confirm
})
china_prov
geopandas使用
接下来,使用geopandas,看了一个大神的博客,写得很详细了。
这里是网址:
(数据科学学习手札74)基于geopandas的空间数据分析——数据结构篇 - 费弗里 - 博客园
https://www.cnblogs.com/feffery/p/11898190.html
这位高人,介绍很系统了。分成好几篇博客,看完对geo的理解更深刻一些。
这里我直接读取中国地图的数据,
china = gpd.read_file("region_map/MLgis/feifuli3_geometry/china_provinces/china_provinces.shp")
fig, ax = plt.subplots(figsize=(12, 8))
ax = china.geometry.plot(ax = ax )
这个地图做出来,是不太常见的投影方式或者坐标系,因此不好看,所以把投影方式改成:
albers_proj = '+proj=aea +lat_1=25 +lat_2=47 +lon_0=105'
fig, ax = plt.subplots(figsize=(12, 8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax)
fig, ax = plt.subplots(figsize=(12, 8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
facecolor = 'grey',
edgecolor = 'whit
这样基本就得到了中国地图。
其中 shp文件,我从网上下载的。如有必要可以上传。
另外 各地区的疫情数据为了防止边,转成json格式的。贴上无所谓:
china_prov
china_prov.to_json()
china_prov2 = pd.read_json('{"prov":{"0":"\u6e56\u5317","1":"\u53f0\u6e7e","2":"\u9999\u6e2f","3":"\u5e7f\u4e1c","4":"\u4e0a\u6d77","5":"\u9ed1\u9f99\u6c5f","6":"\u6c5f\u82cf","7":"\u6cb3\u5357","8":"\u6d59\u6c5f","9":"\u4e91\u5357","10":"\u6cb3\u5317","11":"\u798f\u5efa","12":"\u56db\u5ddd","13":"\u6e56\u5357","14":"\u5317\u4eac","15":"\u5b89\u5fbd","16":"\u65b0\u7586","17":"\u6c5f\u897f","18":"\u5c71\u4e1c","19":"\u9655\u897f","20":"\u91cd\u5e86","21":"\u5409\u6797","22":"\u5929\u6d25","23":"\u8fbd\u5b81","24":"\u5185\u8499\u53e4","25":"\u5e7f\u897f","26":"\u5c71\u897f","27":"\u7518\u8083","28":"\u6d77\u5357","29":"\u8d35\u5dde","30":"\u5b81\u590f","31":"\u6fb3\u95e8","32":"\u9752\u6d77","33":"\u897f\u85cf"},"/confirm/i":{"0":68298,"1":16223,"2":12217,"3":3177,"4":2603,"5":1702,"6":1599,"7":1540,"8":1448,"9":1424,"10":1317,"11":1282,"12":1208,"13":1182,"14":1124,"15":1008,"16":980,"17":937,"18":933,"19":671,"20":603,"21":574,"22":487,"23":455,"24":419,"25":298,"26":260,"27":199,"28":190,"29":147,"30":77,"31":71,"32":18,"33":1}}')
china_prov2
然后接下来就是合并数据了。
使用geopandas读入的china 是一个geoDataframe格式的。
但是可以当做普通数据表对待,直接合并就可以。
合并之前注意到,china 的 NAME 是各省名字,和我们原有的疫情数据的prov 不一样。
所以要先处理成统一昂的数据。
china['prov_name'] = china['NAME'].str.replace('省', '')
china['prov_name'] = china['prov_name'].str.replace('市', '')
china['prov_name'] = china['prov_name'].str.replace('自治区', '')
china['prov_name'] = china['prov_name'].str.replace(r'壮族|回族|维吾尔', '')
china['prov_name']
生成一个“prov_name”,和疫情数据中“prov”对应。这样合并。
data_with_geometry = pd.merge(left = china_prov,
right = china,
left_on='prov',
right_on = 'prov_name',
how = 'left')
合并之后,还要改变投影方式,
data_with_geometry = gpd.GeoDataframe(data_with_geometry, crs = 'EPSG:4326')
接下来就可以作图了。
fig, ax =plt.subplots(figsize=(12, 8))
ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
column = '/confirm/i',
cmap = 'Reds',
missing_kwds = {
"color":"lightgrey",
"edgecolor":"black",
"hatch":"///"
})
只不过这样的作图方式,湖北省颜色唯一最深的,其他地区都一样,没有层次。
所以设置一下scheme。
fig, ax = plt.subplots(figsize=(12, 8))
ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
column = '/confirm/i',
cmap = 'Reds',
legend = True,
scheme = 'NaturalBreaks',
k = 5 ,
legend_kwds = {
"loc":"lower left",
"title":'确诊数量分级',
"shadow":True
})
这样就ok了。
这个过程关键就是合并地图数据和分析数据。geopandas就是强,直接和。非常方便。



