这是我们python课的一个小作业,利用学习到的python numpy, matplotlib, Pandas 等库来可视化全国各省新冠肺炎的地图和某省各个城市的新冠肺炎确症人数的条形统计图。
环境用的是 pycharm,还需要用到包basemap和pyproj,可以选择在anaconda中安装
注意:basemap和pyproj包的版本要和编译器的版本一致。
所需资料存在阿里云盘:阿里云盘分享
主函数
def main():
parser = argparse.ArgumentParser(description="Please input a province's name to get a Bar of nCovDailyData")
parser.add_argument('-p', '--province', default='上海') # 获取要查询的省份
args = parser.parse_args()
print(args)
province = args.province
print('you input is {}'.format(province))
data_provinces, data_cities = get_data(province)
get_map(data_provinces) # 画中国疫情地图
get_bar(data_cities, province) # 画要查询省份城市的柱状图
if __name__ == "__main__":
main()
绘制疫情地图函数
# get_map绘制各个省确症人数地图
def get_map(data):
font_14 = FontProperties(fname='.simsunsimsun.ttf', size=14) # 设置文件中的字体,大小14
font_11 = FontProperties(fname='.simsunsimsun.ttf', size=11) # 设置文件中的字体,大小11
handles = [ # 图例方块
matplotlib.patches.Patch(color='#ffaa85', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#ff7b69', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#bf2121', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#7f1818', alpha=1, linewidth=0),
]
labels = ['1-9', '10-99', '100-999', '>1000人'] # 图例标签
provincePos = { # 各个省的经纬度,构造字典
"辽宁省": [121.7, 40.9],
"吉林省": [124.5, 43.5],
"黑龙江省": [125.6, 46.5],
"北京市": [116.0, 39.9],
"天津市": [117.0, 38.7],
"内蒙古自治区": [110.0, 41.5],
"宁夏回族自治区": [105.2, 37.0],
"山西省": [111.0, 37.0],
"河北省": [114.0, 37.8],
"山东省": [116.5, 36.0],
"河南省": [111.8, 33.5],
"陕西省": [107.5, 33.5],
"湖北省": [111.0, 30.5],
"江苏省": [119.2, 32.5],
"安徽省": [115.5, 31.8],
"上海市": [121.0, 31.0],
"湖南省": [110.3, 27.0],
"江西省": [114.0, 27.0],
"浙江省": [118.8, 28.5],
"福建省": [116.2, 25.5],
"广东省": [113.2, 23.1],
"台湾省": [120.5, 23.5],
"海南省": [108.0, 19.0],
"广西壮族自治区": [107.3, 23.0],
"重庆市": [106.5, 29.5],
"云南省": [101.0, 24.0],
"贵州省": [106.0, 26.5],
"四川省": [102.0, 30.5],
"甘肃省": [103.0, 35.0],
"青海省": [95.0, 35.0],
"新疆维吾尔自治区": [85.5, 42.5],
"西藏自治区": [85.0, 31.5],
"香港特别行政区": [115.1, 21.2],
"澳门特别行政区": [112.5, 21.2]
}
width = 1600
height = 800
fig = matplotlib.figure.Figure() # 创建画图对象
fig.set_size_inches(width / 100, height / 100) # 设置绘图板尺寸
axes = plt.gca() # 获得当前图形的坐标轴
# 兰博托投影模式,局部
m = Basemap(projection='lcc', llcrnrlon=77, llcrnrlat=14, urcrnrlon=140, urcrnrlat=51, lat_1=33, lat_2=45,
lon_0=100, ax=axes)
m.readshapefile('./shapefiles/china', 'province', drawbounds=True) # 画出中国的各个省边界线
m.readshapefile('./shapefiles/china_nine_dotted_line', 'section', drawbounds=True)
m.drawcoastlines(color='black') # 洲际线
m.drawcountries(color='black') # 国界线
pset = set()
# 将m.province_info 中的数据读入到 info 中。Info是个字典。其中一条数据的格式如下:通过读取关键字为 OWNER 并且去掉后面的x00,可以得到所在的省份。
for info, shape in zip(m.province_info, m.province):
pname = info['OWNER'].strip('x00')
fcname = info['FCNAME'].strip('x00')
if pname != fcname: # 如果 FCNAME里的名字跟 OWNER里的名字不同说明是海岛,就不画。
continue
for key in data.keys():
if key in pname:
if data[key] == 0:
color = '#f0f0f0'
elif data[key] < 10:
color = '#ffaa85'
elif data[key] < 100:
color = '#ff7b69'
elif data[key] < 1000:
color = '#bf2121'
else:
color = '#7f1818'
break
poly = Polygon(shape, facecolor=color, edgecolor=color)
axes.add_patch(poly)
pos = provincePos[pname]
# 在地图添加各个省份的名字文本标
text = pname.replace("自治区", "").replace("特别行政区", "").replace("壮族", "").replace("维吾尔", "").replace("回族",
"").replace(
"省", "").replace("市", "")
if text not in pset:
x, y = m(pos[0], pos[1])
axes.text(x, y, text, fontproperties=font_11, color='#000000')
pset.add(text)
axes.legend(handles, labels, bbox_to_anchor=(0.5, -0.11), loc='lower center', ncol=4, prop=font_11) # 画图例
axes.set_title("2020-nCov 疫情地图-确诊情况统计", fontproperties=font_14) # 标题
plt.show()
绘制图如下
统计城市疫情柱状图
# 绘制某省各个城市确症人数条形图
def get_bar(data, province):
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置rc参数显示中文标题,设置字体为SimHei显示中文
cities = list(data.keys()) # 获取城市
count = list(data.values()) # 获取确诊人数
plt.figure(figsize=(10, 5)) # 设置画布的尺寸
plt.title(province + '各地确诊人数统计', fontsize=20) # 标题,并设置字号大小
# alpha: 透明度 width:柱子的宽度 face color:柱子填充色 edge color: 柱子轮廓色 lw: 柱子轮廓宽度 label: 图例
rect_bar = plt.barh(cities, count, alpha=0.6, label='确诊统计数字')
# 添加数据标签,矩形上面的数值
for rect in rect_bar:
width = rect.get_width()
plt.text(width + 3, rect.get_y() + 0.3, str(width) + '人', ha="center", va="bottom")
plt.legend(loc=4) # 图例展示位置,数字代表第几象
plt.show()
运行结果如图
用到的库
import argparse import matplotlib import pandas as pd from matplotlib import pyplot as plt from matplotlib.font_manager import FontProperties from matplotlib.patches import Polygon from mpl_toolkits.basemap import Basemap



