使用geopandas 制作中国疫情地图

最近要做一个中国地图,以前用pyecharts,最近接触了geopandas 觉得很强大,改用geopandas作图。比如我制作一个疫情分布地图,效果应该是这样的。最终效果。

首先导入需要用的库:

import pandas as pd
import matplotlib.pyplot as plt
import requests
import geopandas as gpd
plt.rcParams['font.family'] = 'SimHei'

 然后使用爬虫把疫情数据怕取下来,我使用的是 手机端的网易数据接口,地址是,

实时更新|新冠肺炎疫情动态地图icon-default.png?t=L892https://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']

confirm = [c['total']['confirm'] for c in children]
print(confirm)

做成一个dataframe,以便后面使用


china_prov = pd.DataFrame({
    "prov":prov,
    "confirm":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":{"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',
                                                 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',
                                                 cmap = 'Reds',
                                                 legend = True,
                                                 scheme = 'NaturalBreaks',
                                                 k = 5 ,
                                                 legend_kwds = {
                                                     "loc":"lower left",
                                                     "title":'确诊数量分级',
                                                     "shadow":True
                                                 })

这样就ok了。

这个过程关键就是合并地图数据和分析数据。geopandas就是强,直接和。非常方便。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值