
利用Python实现新冠疫情数据可视化(获取疫情历史数据,制作南丁格尔玫瑰图、疫情地图、动态疫情组合图、词云)
文章目录前言从今年年初爆发的新冠疫情,截止至当前9.21,全球累计确诊人数已超三千万,死亡人数近百万,这对于世界各国人民而言无疑是一场巨大的灾难。当前国内疫情局势已基本稳定,而美国、印度、巴西等国家的感染人数仍以较快的速度持续增长,情况不容乐观。本文利用Python的pyecharts与matplotlib库制作了一些疫情可视化图来展现全球疫情的发展趋势,由于本人才疏学浅,难免有纰漏,欢迎指正。1
文章目录
前言
从今年年初爆发的新冠疫情,截止至2020.09.21,全球累计确诊人数已超三千万,死亡人数近百万,这对于世界各国人民而言无疑是一场巨大的灾难。当前国内疫情局势已基本稳定,而美国、印度、巴西等国家的感染人数仍以较快的速度持续增长,情况不容乐观。
本文利用Python的pyecharts与matplotlib库制作了一些疫情可视化图来展现全球疫情的发展趋势,供初学者参考。代码比较野生,难免有所纰漏,欢迎指正。
1.获取疫情历史数据
疫情的历史数据可以从丁香园、或者百度疫情获取,也可以从GitHub上诸位大神提供的接口获取。本文的数据来源于https://github.com/canghailan/Wuhan-2019-nCoV中的Wuhan-2019-nCoV.csv文件,十分感谢大神的整理,也希望大家能够star,整理不易,这里向所有提供免费疫情数据的朋友表示敬意。
本文使用的数据统计截止日期为2020.09.21。
2.制作南丁格尔玫瑰图
人民日报与央视新闻官微早前发布过两张很漂亮的疫情玫瑰图,本文的玫瑰图主要仿制于此,使用的是matplotlib库,当然也可以通过pyecharts实现,代码也不复杂,有兴趣的朋友可以自己尝试。
图片如下:
2.1 全球各国确诊人数玫瑰图
#coding:utf-8
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def rosetype_pie(country,confirmed,size,colors):
plt.rcParams['font.sans-serif'] = ['SimHei'] # 中文显示
num= len(size) # 柱子的数量
width = 2 * np.pi / num # 每个柱子的宽度
rad = np.cumsum([width] * num) # 每个柱子的角度
plt.figure(figsize=(8, 8),dpi=500,) # 创建画布
ax = plt.subplot(projection='polar')
ax.set_ylim(-1, np.ceil(max(size) + 1)) # 中间空白,-1为空白半径大小,可自行调整
ax.set_theta_zero_location('N',-5.0) # 设置极坐标的起点方向 W,N,E,S, -5.0为偏离数值,可自行调整
ax.set_theta_direction(1) # 1为逆时针,-1为顺时针
ax.grid(False) # 不显示极轴
ax.spines['polar'].set_visible(False) # 不显示极坐标最外的圆形
ax.set_yticks([]) # 不显示坐标间隔
ax.set_thetagrids([]) # 不显示极轴坐标
ax.bar(rad, size, width=width, color=colors, alpha=1) # 画图
ax.bar(rad, 1, width=width, color='white', alpha=0.15) # 中间添加白色色彩使图案变浅
ax.bar(rad, 3, width=width, color='white', alpha=0.1) # 中间添加白色色彩使图案变浅
ax.bar(rad, 5, width=width, color='white', alpha=0.05) # 中间添加白色色彩使图案变浅
ax.bar(rad, 7, width=width, color='white', alpha=0.03) # 中间添加白色色彩使图案变浅
# 设置text
for i in np.arange(num):
if i < 8:
ax.text(rad[i], # 角度
size[i]-0.2, # 长度
country[i]+'\n'+str(confirmed[i])+'例', # 文本
rotation=rad[i] * 180 / np.pi -5, # 文字角度
rotation_mode='anchor',
# alpha=0.8,#透明度
fontstyle='normal',# 设置字体类型,可选参数[ ‘normal’ | ‘italic’ | ‘oblique’ ],italic斜体,oblique倾斜
fontweight='black', # 设置字体粗细,可选参数 [‘light’, ‘normal’, ‘medium’, ‘semibold’, ‘bold’, ‘heavy’, ‘black’]
color='white', # 设置字体颜色
size=size[i]/2.2, # 设置字体大小
ha="center", # 'left','right','center'
va="top", # 'top', 'bottom', 'center', 'baseline', 'center_baseline'
)
elif i < 15:
ax.text(rad[i]+0.02,
size[i]-0.7,
country[i] + '\n' + str(confirmed[i]) + '例',
fontstyle='normal',
fontweight='black',
color='white',
size=size[i] / 1.6,
ha="center",
)
else:
ax.text(rad[i],
size[i]+0.1,
str(confirmed[i]) + '例 ' + country[i],
rotation=rad[i] * 180 / np.pi + 85,
rotation_mode='anchor',
fontstyle='normal',
fontweight='black',
color='black',
size=4,
ha="left",
va="bottom",
)
plt.show()
if __name__ == '__main__':
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 利用pandas读取数据
colors = [(0.68359375, 0.02734375, 0.3203125),
(0.78125, 0.05078125, 0.2578125),
(0.875, 0.0390625, 0.1796875),
(0.81640625, 0.06640625, 0.0625),
(0.8515625, 0.1484375, 0.08203125),
(0.90625, 0.203125, 0.13671875),
(0.89453125, 0.2890625, 0.0703125),
(0.84375, 0.2421875, 0.03125),
(0.9140625, 0.26953125, 0.05078125),
(0.85546875, 0.31640625, 0.125),
(0.85546875, 0.3671875, 0.1171875),
(0.94921875, 0.48046875, 0.28125),
(0.9375, 0.51171875, 0.1484375),
(0.93359375, 0.59765625, 0.0625),
(0.93359375, 0.62890625, 0.14453125),
(0.86328125, 0.5859375, 0.15234375),
(0.86328125, 0.71875, 0.16015625),
(0.86328125, 0.8203125, 0.16015625),
(0.76171875, 0.8671875, 0.16015625),
(0.53125, 0.85546875, 0.15625),
(0.4765625, 0.94140625, 0.0703125),
(0.21484375, 0.91015625, 0.0625),
(0.15234375, 0.88671875, 0.08203125),
(0.11328125, 0.87890625, 0.19921875),
(0.11328125, 0.8125, 0.1796875),
(0.1875, 0.76953125, 0.2109375),
(0.2109375, 0.78125, 0.38671875),
(0.1484375, 0.76953125, 0.30859375),
(0.22265625, 0.73046875, 0.35546875),
(0.2890625, 0.6875, 0.4765625)] # 转化为小数的rgb色列表,
df_top_confirmed = df.loc[(df['date'] == '2020-09-21') & (df['province'].isnull())].sort_values('confirmed',ascending=False).head(30) # 选择9.21日确诊数前三十的国家
country = df_top_confirmed['country'].tolist()
confirmed = df_top_confirmed['confirmed'].tolist()
size = [22 , 19, 17, 12, 11, 10, 9, 8, 7.2, 7.0, 6.8, 6.6, 6.4, 6.2, 6.0, 5.8, 5.6, 5.4, 5.2, 5.0, 4.8, 4.6, 4.4, 4.2, 4.0, 3.8, 3.6, 3.4, 3.2, 3.0] # 自定义一个柱长度列
rosetype_pie(country, confirmed, size, colors)
以上代码可得到的图如下:
2.2 全国各省市零新增天数玫瑰图
#coding:utf-8
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def get_data():
colors = [
'#FAE927', '#E9E416', '#C9DA36', '#9ECB3C', '#6DBC49',
'#37B44E', '#3DBA78', '#14ADCF', '#209AC9', '#1E91CA',
'#2C6BA0', '#2B55A1', '#2D3D8E', '#44388E', '#6A368B',
'#7D3990', '#A63F98', '#C31C88', '#D52178', '#D5225B',
'#D02C2A', '#D44C2D', '#F57A34', '#FA8F2F', '#D99D21',
]
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 利用pandas读取数据
df_province = df.loc[(~df['province'].isnull()) & (df['city'].isnull())] # 找到新中国各省、自治区的数据
trans_list = ['湖北','广东','北京','吉林','上海','浙江','安徽','江西','山东','广西','海南','四川','贵州','云南','宁夏','天津','山西','黑龙江','河南','湖南','重庆','河北','辽宁','江苏','福建','陕西','台湾','香港','澳门','内蒙','甘肃','新疆','青海','西藏'] # 对于中国省、自治区重命名,方便后续操作
def transfer(x):
for i in trans_list:
if i[:2] == x[:2]:
return i
df_province['pro'] = df_province['province'].apply(transfer) # 新增一列重命名后的省自治区名字
df_province.drop('province', axis=1, inplace=True) # 删除原来的province列
df_province.rename(columns={'pro': 'province'}, inplace=True) # 将新增列重命名为province
df_province.to_csv('china_province_data.csv',index=0) # 保存至本地,方便后续操作
province_list = df_province['province'].unique().tolist() # 各省/区的名字列表
increase_day_list = []
for i in province_list:
df_province_i = df_province.loc[df_province['province'] == i] # 定位到省
df_province_i_confirm_list = df_province_i['confirmed'].tolist()[::-1] # 获取确诊总人数列表,并倒序,将最近的日期放在列表最前面
increase_day = 0
for j in range(len(df_province_i_confirm_list) - 1):
if df_province_i_confirm_list[j] == df_province_i_confirm_list[j + 1]: # 判断该元素与下一个是否相等,如果相等计数+1,如果不等跳出循环,最后的计数值就是零增长天数
increase_day += 1
else:
break
increase_day_list.append(increase_day)
df1 = pd.DataFrame(data=increase_day_list,index=province_list,columns=['num']) # 创建df,排序,并除去0天的省份与数值
df1 = df1.sort_values('num', ascending=False)
df1 = df1.loc[df1['num'] != 0]
province = df1.index.tolist()
num = df1['num'].tolist()
size = [22, 19, 17, 12, 11, 10, 9, 6.8, 6.6, 6.4, 6.2, 6.0, 5.8, 5.6, 5.4, 4.4, 4.2, 4.0, 3.8, 3.6, 2.4, 2.0, 1.8, 1.6, 1.4] # 自定义柱长列表
rosetype_pie(province,num,size, colors)
def rosetype_pie(province,num,size,colors):
plt.rcParams['font.sans-serif'] = ['SimHei']
n= len(num)
width = 2 * np.pi / n
rad = np.cumsum([width] * n)
plt.figure(figsize=(10, 10),dpi=500,)
ax = plt.subplot(projection='polar')
ax.set_ylim(-8, np.ceil(max(size) + 1))
ax.set_theta_zero_location('N',5.0)
ax.set_theta_direction(-1)
ax.grid(False)
ax.spines['polar'].set_visible(False)
ax.set_yticks([])
ax.set_thetagrids([])
ax.bar(rad, size, width=width, color=colors, alpha=1)
ax.set_title("零新增", x=0.50,y=0.42,fontdict={'family':'Microsoft YaHei', 'size':50,'color':'#003366','fontweight':'heavy',}) # 设置标题
ax.text(0.15*np.pi,-7.5," 多个省区市 \n确诊病例连续多日",fontdict={'family':'Microsoft YaHei', 'size':20,'color':'#003366','fontweight':'heavy'},ha="center",va="baseline",) # 设置文字
# 设置天数标签
for i in np.arange(n):
if i < 3:
ax.text(rad[i],
size[i]-4,
str(num[i])+'天',
fontstyle='normal',
fontweight='black',
fontdict={'family':'Microsoft YaHei', 'size':size[i],'color':'#003366',},
ha="center",
va="center",
)
elif i <7:
ax.text(rad[i]+0.06,
size[i]-2,
str(num[i]) + '天',
fontstyle='normal',
fontweight='black',
fontdict={'family': 'Microsoft YaHei', 'size': 12,'color':'white',},
ha="center",
va="center",
)
elif i <15:
ax.text(rad[i]+0.02,
size[i]-1.1,
str(num[i]) + '天',
fontstyle='normal',
fontweight='black',
fontdict={'family': 'Microsoft YaHei', 'size':11,'color':'white',},
ha="center",
va="center",
)
elif i< 20:
ax.text(rad[i]-0.06,
size[i]-0.8,
str(num[i]) + '天',
fontstyle='normal',
fontweight='black',
fontdict={'family': 'Microsoft YaHei', 'size': 9,'color':'white',},
ha="center",
va="center",
)
else:
ax.text(rad[i],
size[i]-0.7,
str(num[i]) + '天',
fontstyle='normal',
fontweight='black',
fontdict={'family': 'Microsoft YaHei', 'size': 9,'color':'white',},
ha="center",
va="center",
)
# 设置省份标签
for i in np.arange(n):
if i < 3:
ax.text(rad[i] - 0.01,
size[i] - 2,
province[i],
# alpha=0.8,#透明度
fontstyle='normal',
fontweight='black',
color='#003366',
size=size[i],
ha="center",
va="center",
)
elif i < 7:
ax.text(rad[i] - 0.03,
size[i] - 1.7,
province[i],
fontstyle='normal',
fontweight='black',
color='white',
size=12,
ha="center",
va="center",
)
elif i < 15:
ax.text(rad[i]-0.03,
size[i] - 2.3,
province[i],
fontstyle='normal',
fontweight='black',
color='white',
size=10,
ha="center",
va="center",
)
elif i < 20:
ax.text(rad[i]+0.04,
size[i] - 1.2,
province[i],
fontstyle='normal',
fontweight='black',
color='white',
size=9,
ha="center",
va="center",
)
else:
ax.text(rad[i],
size[i] +1,
province[i],
fontstyle='normal',
fontweight='black',
color=colors[i],
size=8,
ha="center",
va="center",
)
plt.show()
if __name__ == '__main__':
get_data()
运行以上代码可得如下图。按照例图的样式来设置文字标签还是比较繁琐的。
3.制作疫情地图
制作疫情地图主要使用pyecharts库,官方文档里有实例可参考,链接:https://gallery.pyecharts.org/#/Map/README。
3.1全国各省市目前确诊总人数疫情地图
# coding:utf-8
from pyecharts import options as opts
from pyecharts.charts import Map
import pandas as pd
def china_map(data_pair):
Map(init_opts=opts.InitOpts(theme='dark', width='1600px', height='900px')
).add(
series_name="",
data_pair=data_pair,
maptype="china",
label_opts=opts.LabelOpts(
is_show=True,
position='inside',
),
is_map_symbol_show=False,
).set_global_opts(
title_opts=opts.TitleOpts(
title="全国新冠疫情地图",
pos_left="center",
pos_top="20",
title_textstyle_opts=opts.TextStyleOpts(
font_size=24,
font_family="Microsoft YaHei"),
subtitle='统计时间截止至2020.09.21 21时',
subtitle_textstyle_opts=opts.TextStyleOpts(
font_size=12, font_family="Microsoft YaHei"),
),
tooltip_opts=opts.TooltipOpts(
is_show=True,
formatter="{b} : 确诊{c}人",
),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True,
dimension=0,
pos_left="10",
pos_bottom="20",
pieces=[
{'max': 9, 'min': 0, 'label': '0-9', 'color': '#FFFFCC'},
{'max': 99, 'min': 10, 'label': '10-99', 'color': '#FFC4B3'},
{'max': 499, 'min': 100, 'label': '100-499', 'color': '#FF9985'},
{'max': 999, 'min': 500, 'label': '500-999', 'color': '#F57567'},
{'max': 4999, 'min': 1000, 'label': '1000-4999', 'color': '#E64546'},
{'max': 9999, 'min': 5000, 'label': '5000-9999', 'color': '#B80909'},
{'max': 49999, 'min': 10000, 'label': '10000-49999', 'color': '#8A0808'},
{'max': 99999, 'min': 50000, 'label': '>=50000', 'color': '#660000'}
]
)
).render('中国疫情地图.html')
if __name__ == '__main__':
df = pd.read_csv('china_province_data.csv') # 利用pandas读取数据
province_list = df[df['date']=='2020-09-21']['province'].tolist() # 各省/区的名字列表
data_list = df[df['date']=='2020-09-21']['confirmed'].tolist() # 数据
data_pair = [x for x in zip(province_list, data_list)]
china_map(data_pair)
得到的可视化图如下:
3.2全球各国家与地区目前确诊总人数疫情地图
#coding:utf-8
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.commons.utils import JsCode
# 国家名称中英文映射表,已根据疫情数据中的中文名称进行对应矫正,操作较为麻烦,目前尚有一些缺失国家及地区。此文暂不涉及。
name_map = {'Liechtenstein': '列支敦士登', 'Morocco': '摩洛哥', 'W. Sahara': '西撒哈拉', 'Serbia': '塞尔维亚', 'Afghanistan': '阿富汗',
'Angola': '安哥拉', 'Albania': '阿尔巴尼亚', 'Aland': '奥兰群岛', 'Andorra': '安道尔',
'United Arab Emirates': '阿联酋', 'Argentina': '阿根廷', 'Armenia': '亚美尼亚', 'American Samoa': '美属萨摩亚',
'Fr. S. Antarctic Lands': '法属南半球和南极领地', 'Antigua and Barb.': '安提瓜和巴布达', 'Australia': '澳大利亚',
'Austria': '奥地利', 'Azerbaijan': '阿塞拜疆', 'Burundi': '布隆迪', 'Belgium': '比利时', 'Benin': '贝宁',
'Burkina Faso': '布基纳法索', 'Bangladesh': '孟加拉国', 'Bulgaria': '保加利亚', 'Bahrain': '巴林', 'Bahamas': '巴哈马',
'Bosnia and Herz.': '波黑', 'Belarus': '白俄罗斯', 'Belize': '伯利兹', 'Bermuda': '百慕大', 'Bolivia': '玻利维亚',
'Brazil': '巴西', 'Barbados': '巴巴多斯', 'Brunei': '文莱', 'Bhutan': '不丹', 'Botswana': '博茨瓦纳',
'Central African Rep.': '中非', 'Canada': '加拿大', 'Switzerland': '瑞士', 'Chile': '智利', 'China': '中国',
"Côte d'Ivoire": '科特迪瓦', 'Cameroon': '喀麦隆', 'Dem. Rep. Congo': '刚果(布)', 'Congo': '刚果(金)',
'Colombia': '哥伦比亚', 'Comoros': '科摩罗', 'Cape Verde': '佛得角', 'Costa Rica': '哥斯达黎加', 'Cuba': '古巴',
'Curaçao': '库拉索', 'Cayman Is.': '开曼群岛', 'N. Cyprus': '北塞浦路斯', 'Cyprus': '塞浦路斯', 'Czech Rep.': '捷克',
'Germany': '德国', 'Djibouti': '吉布提', 'Denmark': '丹麦', 'Dominican Rep.': '多米尼加',
'Algeria': '阿尔及利亚', 'Ecuador': '厄瓜多尔', 'Egypt': '埃及', 'Eritrea': '厄立特里亚', 'Spain': '西班牙',
'Estonia': '爱沙尼亚', 'Ethiopia': '埃塞俄比亚', 'Finland': '芬兰', 'Fiji': '斐济', 'Falkland Is.': '福克兰群岛(马尔维纳斯)',
'France': '法国', 'Faeroe Is.': '法罗群岛', 'Micronesia': '密克罗尼西亚', 'Gabon': '加蓬', 'United Kingdom': '英国',
'Georgia': '格鲁吉亚', 'Ghana': '加纳', 'Guinea': '几内亚', 'Gambia': '冈比亚', 'Guinea-Bissau': '几内亚比绍',
'Eq. Guinea': '赤道几内亚', 'Greece': '希腊', 'Grenada': '格林纳达', 'Greenland': '格陵兰', 'Guatemala': '危地马拉',
'Guam': '关岛', 'Heard I. and McDonald Is.': '赫德岛和麦克唐纳群岛', 'Honduras': '洪都拉斯',
'Croatia': '克罗地亚', 'Haiti': '海地', 'Hungary': '匈牙利', 'Indonesia': '印度尼西亚', 'Isle of Man': '英国属地曼岛',
'India': '印度', 'Br. Indian Ocean Ter.': '英属印度洋领土', 'Ireland': '爱尔兰', 'Iran': '伊朗', 'Iraq': '伊拉克',
'Iceland': '冰岛', 'Israel': '以色列', 'Italy': '意大利', 'Jamaica': '牙买加', 'Jersey': '泽西岛', 'Jordan': '约旦',
'Japan': '日本', 'Siachen Glacier': '锡亚琴冰川', 'Kazakhstan': '哈萨克斯坦', 'Kenya': '肯尼亚',
'Kyrgyzstan': '吉尔吉斯斯坦', 'Cambodia': '柬埔寨', 'Kiribati': '基里巴斯', 'Korea': '韩国', 'Kuwait': '科威特',
'Lao PDR': '老挝', 'Lebanon': '黎巴嫩', 'Liberia': '利比里亚', 'Libya': '利比亚', 'Saint Lucia': '圣卢西亚',
'Sri Lanka': '斯里兰卡', 'Lesotho': '莱索托', 'Lithuania': '立陶宛', 'Luxembourg': '卢森堡', 'Latvia': '拉脱维亚',
'Moldova': '摩尔多瓦', 'Madagascar': '马达加斯加', 'Mexico': '墨西哥', 'Macedonia': '北马其顿', 'Mali': '马里',
'Malta': '马耳他', 'Myanmar': '缅甸', 'Montenegro': '黑山', 'Mongolia': '蒙古', 'N. Mariana Is.': '北马里亚纳',
'Mozambique': '莫桑比克', 'Mauritania': '毛利塔尼亚', 'Montserrat': '蒙特塞拉特', 'Mauritius': '毛里求斯',
'Malawi': '马拉维', 'Malaysia': '马来西亚', 'Namibia': '纳米比亚', 'New Caledonia': '新喀里多尼亚', 'Niger': '尼日尔',
'Nigeria': '尼日利亚', 'Nicaragua': '尼加拉瓜', 'Niue': '纽埃', 'Netherlands': '荷兰', 'Norway': '挪威',
'Nepal': '尼泊尔', 'New Zealand': '新西兰', 'Oman': '阿曼', 'Pakistan': '巴基斯坦', 'Panama': '巴拿马', 'Peru': '秘鲁',
'Philippines': '菲律宾', 'Palau': '帕劳', 'Papua New Guinea': '巴布亚新几内亚', 'Poland': '波兰',
'Puerto Rico': '波多黎各', 'Dem. Rep. Korea': '朝鲜', 'Portugal': '葡萄牙', 'Paraguay': '巴拉圭',
'Palestine': '巴勒斯坦', 'Fr. Polynesia': '法属波利尼西亚', 'Qatar': '卡塔尔', 'Romania': '罗马尼亚', 'Russia': '俄罗斯',
'Rwanda': '卢旺达', 'Saudi Arabia': '沙特阿拉伯', 'Sudan': '苏丹', 'S. Sudan': '南苏丹', 'Senegal': '塞内加尔',
'Singapore': '新加坡', 'S. Geo. and S. Sandw. Is.': '南乔治亚岛和南桑威奇群岛', 'Saint Helena': '圣赫勒拿',
'Solomon Is.': '所罗门群岛', 'Sierra Leone': '塞拉利昂', 'El Salvador': '萨尔瓦多',
'St. Pierre and Miquelon': '圣皮埃尔和密克隆', 'São Tomé and Principe': '圣多美和普林西比', 'Suriname': '苏里南',
'Slovakia': '斯洛伐克', 'Slovenia': '斯洛文尼亚', 'Sweden': '瑞典', 'Swaziland': '斯威士兰', 'Seychelles': '塞舌尔',
'Syria': '叙利亚', 'Turks and Caicos Is.': '特克斯和凯科斯群岛', 'Chad': '乍得', 'Togo': '多哥', 'Thailand': '泰国',
'Tajikistan': '塔吉克斯坦', 'Turkmenistan': '土库曼斯坦', 'Timor-Leste': '东帝汶', 'Tonga': '汤加',
'Trinidad and Tobago': '特立尼达和多巴哥', 'Tunisia': '突尼斯', 'Turkey': '土耳其', 'Tanzania': '坦桑尼亚',
'Uganda': '乌干达', 'Ukraine': '乌克兰', 'Uruguay': '乌拉圭', 'United States': '美国', 'Uzbekistan': '乌兹别克斯坦',
'St. Vin. and Gren.': '圣文森特和格林纳丁斯', 'Venezuela': '委内瑞拉', 'U.S. Virgin Is.': '美属维尔京群岛', 'Vietnam': '越南',
'Vanuatu': '瓦努阿图', 'Samoa': '萨摩亚', 'Yemen': '也门', 'South Africa': '南非', 'Zambia': '赞比亚',
'Zimbabwe': '津巴布韦', 'Somalia': '索马里', "Anguilla": "安圭拉", 'Dominica': '多米尼克','Gibraltar': '直布罗陀',
'Guyana': '圭亚那','Saint Kitts and Nevis': '圣基茨和尼维斯','Monaco': '摩纳哥','Maldives': '马尔代夫','San Marino': '圣马力诺',
'Vatican City': '梵蒂冈','British Virgin Islands': '英属维尔京群岛'}
def get_data():
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 利用pandas读取数据
df = df.loc[(df['date'] == '2020-09-21') & (df['province'].isnull())] # 定位到最近日期然后筛选国家
country = df['country'].tolist() # 国家
confirmed = df['confirmed'].tolist() # 确诊人数
cure = df['cured'].tolist() # 治愈人数
death = df['dead'].tolist() # 死亡人数
data_pair = {(i, (j, x, y)) for i, j, x, y in zip(country, confirmed, cure, death)}
draw_global_pics(data_pair)
# print(data_pair)
def draw_global_pics(data_pair):
# jscode,用来显示数据
mapformatter = """
function (params, ticket, callback) {
var result = '';
var xName = params.name;
var con = params.data.value[0];
var cure = params.data.value[1];
var death = params.data.value[2];
var value = params.value;
result += xName + '<br/>';
result += '确诊人数: ' + value+ '<br/>';
result += '治愈人数: ' + cure + '<br/>';
result += '死亡人数: ' + death + '<br/>';
result += '<br/>';
console.log(params);
return result
}
"""
world_map = (
Map(init_opts=opts.InitOpts(theme='dark',width='2000px',height='1000px'))
.add(
'',
data_pair,
'world',
name_map=name_map,
is_map_symbol_show=False,)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(
title='全球新冠疫情累计确诊人数地图',pos_right='center',pos_top='2%',title_textstyle_opts=opts.TextStyleOpts(
font_size=24, font_family="Microsoft YaHei",
),
subtitle='统计时间截止至2020.09.21',subtitle_textstyle_opts=opts.TextStyleOpts(
font_size=12, color="#CCCCCC",font_family="Microsoft YaHei"
),
),
legend_opts=opts.LegendOpts(is_show=False),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True,
dimension=0,
pos_left="10",
pos_bottom='20',
pieces=[
{'max': 9, 'min': 0, 'label': '0-9', 'color': '#FFFFCC'},
{'max': 99, 'min': 10, 'label': '10-99', 'color': '#FFC4B3'},
{'max': 999, 'min': 100, 'label': '100-999', 'color': '#FF9985'},
{'max': 9999, 'min': 1000, 'label': '1000-9999', 'color': '#F57567'},
{'max': 99999, 'min': 10000, 'label': '10000-99999', 'color': '#E64546'},
{'max': 999999, 'min': 100000, 'label': '100000-999999', 'color': '#B80909'},
{'max': 4999999, 'min': 1000000, 'label': '1000000-4999999', 'color': '#8A0808'},
{'max': 9999999, 'min': 5000000, 'label': '>=5000000', 'color': '#660000'}
]
),
tooltip_opts=opts.TooltipOpts(is_show=True, formatter=JsCode(mapformatter))
)
)
world_map.render('全球疫情地图多组数据.html')
if __name__ == '__main__':
get_data()
得到的可视化地图如下,鼠标移动至国家上面可显示确诊人数、死亡人数等信息,若想添加其他信息可通过修改文中的jscode实现。
3.3全国各省市确诊人数发展趋势动态疫情地图
#coding:utf-8
import pandas as pd
import pyecharts.options as opts
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Timeline,Map
def get_data():
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 利用pandas读取数据
df_province = df.loc[(df['date']>='2020-01-17')&(~df['province'].isnull())&(df['city'].isnull())] # 读取各省、自治区、直辖市历史数据
def transfer(x):
if x.endswith('自治区') or x.endswith('省') or x.endswith('特别行政区') or x.endswith('市'):
return x.replace('壮族', '').replace('维吾尔', '').replace('回族', '').replace('自治区', '').replace('省', '').replace(
'特别行政区', '').replace('市', '')
else:
return x
df_province['province'] = df_province['province'].apply(transfer) # 修改各省、自治区、直辖市的名称,以便map接收
date = df_province['date'].unique().tolist()[:30] # 可自行修改展示的天数
data_list = []
time_list = []
# 将data_list设置成内置dict形式,格式为:[
# {'time': '01.01', 'data': [{'name': '北京', 'value': [0, '北京']},{'name': '天津', 'value': [0, '天津']},]},
# {'time': '01.02', 'data': [{'name': '北京', 'value': [1, '北京']},{'name': '天津', 'value': [1, '天津']},]},
# ]
for i in date:
time = i[5:].replace('-', '.') # 将时间改为 12.01 形式,个人喜好。
time_list.append(time)
data = []
name = df_province.loc[df_province['date'] == i]['province'].tolist()
num = df_province.loc[df_province['date'] == i]['confirmed'].tolist()
for x,y in zip(name,num):
data.append({"name":x,"value":[y,x]})
data_list.append({"time":time,"data":data})
time_line(data_list,time_list)
def get_day_chart(data,day):
map_data = [
[[x["name"], x["value"]] for x in d["data"]] for d in data if d["time"] == day
][0]
map_chart = (
Map()
.add(
series_name="",
data_pair=map_data,
maptype="china",
label_opts=opts.LabelOpts(is_show=False),
is_map_symbol_show=False,
itemstyle_opts={
"normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
"emphasis": {
"label": {"show": Timeline},
"areaColor": "rgba(255,255,255, 0.5)",
},
},
)
.set_global_opts(
title_opts=opts.TitleOpts(
title="新冠疫情全国各省市发展趋势图",
# subtitle="统计截止日期2020.03.01",
pos_left="center",
pos_top="top",
title_textstyle_opts=opts.TextStyleOpts(
font_size=25, color="rgba(255,255,255, 0.9)"
),
),
tooltip_opts=opts.TooltipOpts(
is_show=True,
formatter=JsCode(
"""function(params) {
if ('value' in params.data) {
return params.data.value[1] + ': ' + params.data.value[0];
}
}"""
),
),
visualmap_opts=opts.VisualMapOpts(
is_calculable=True,
dimension=0,
pos_left="10",
pos_top="center",
is_piecewise=True,
pieces=[
{'max': 9, 'min': 0, 'label': '0-9', 'color': '#FFFFCC'},
{'max': 99, 'min': 10, 'label': '10-99', 'color': '#FFC4B3'},
{'max': 999, 'min': 100, 'label': '100-999', 'color': '#FF9985'},
{'max': 9999, 'min': 1000, 'label': '1000-9999', 'color': '#F57567'},
{'max': 19999, 'min': 10000, 'label': '10000-19999', 'color': '#E64546'},
{'max': 29999, 'min': 20000, 'label': '20000-29999', 'color': '#B80909'},
{'max': 39999, 'min': 30000, 'label': '30000-39999', 'color': '#8A0808'},
{'max': 49999, 'min': 40000, 'label': '40000-49999', 'color': '#660000'},
{'max': 99999, 'min': 50000, 'label': '>=50000', 'color': '#660000'}
]
),
)
)
return map_chart
def time_line(data,time_list):
timeline = Timeline(
init_opts=opts.InitOpts(width="1570px", height="720px", theme=ThemeType.DARK)
)
for d in time_list:
g = get_day_chart(data,d)
timeline.add(g, time_point=d)
timeline.add_schema(
orient="vertical",
is_auto_play=True,
is_inverse=True,
play_interval=1000,# 播放速度,单位ms
pos_left="null",
pos_right="5%",
pos_top="20",
pos_bottom="20",
width="50",
label_opts=opts.LabelOpts(is_show=True, color="#fff",interval=7),# interval 标签间隔
)
timeline.render('中国疫情发展趋势.html')
if __name__ == '__main__':
get_data()
运行以上代码可以得到的图预览
3.4全球各大洲、国家与地区确诊人数发展趋势动态组合图
#coding:utf-8
import pandas as pd
import pyecharts.options as opts
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Timeline, Grid, Bar, Map, Pie, Line
name_map = {'Liechtenstein': '列支敦士登', 'Morocco': '摩洛哥', 'W. Sahara': '西撒哈拉', 'Serbia': '塞尔维亚', 'Afghanistan': '阿富汗',
'Angola': '安哥拉', 'Albania': '阿尔巴尼亚', 'Aland': '奥兰群岛', 'Andorra': '安道尔',
'United Arab Emirates': '阿联酋', 'Argentina': '阿根廷', 'Armenia': '亚美尼亚', 'American Samoa': '美属萨摩亚',
'Fr. S. Antarctic Lands': '法属南半球和南极领地', 'Antigua and Barb.': '安提瓜和巴布达', 'Australia': '澳大利亚',
'Austria': '奥地利', 'Azerbaijan': '阿塞拜疆', 'Burundi': '布隆迪', 'Belgium': '比利时', 'Benin': '贝宁',
'Burkina Faso': '布基纳法索', 'Bangladesh': '孟加拉国', 'Bulgaria': '保加利亚', 'Bahrain': '巴林', 'Bahamas': '巴哈马',
'Bosnia and Herz.': '波黑', 'Belarus': '白俄罗斯', 'Belize': '伯利兹', 'Bermuda': '百慕大', 'Bolivia': '玻利维亚',
'Brazil': '巴西', 'Barbados': '巴巴多斯', 'Brunei': '文莱', 'Bhutan': '不丹', 'Botswana': '博茨瓦纳',
'Central African Rep.': '中非', 'Canada': '加拿大', 'Switzerland': '瑞士', 'Chile': '智利', 'China': '中国',
"Côte d'Ivoire": '科特迪瓦', 'Cameroon': '喀麦隆', 'Dem. Rep. Congo': '刚果(布)', 'Congo': '刚果(金)',
'Colombia': '哥伦比亚', 'Comoros': '科摩罗', 'Cape Verde': '佛得角', 'Costa Rica': '哥斯达黎加', 'Cuba': '古巴',
'Curaçao': '库拉索', 'Cayman Is.': '开曼群岛', 'N. Cyprus': '北塞浦路斯', 'Cyprus': '塞浦路斯', 'Czech Rep.': '捷克',
'Germany': '德国', 'Djibouti': '吉布提', 'Denmark': '丹麦', 'Dominican Rep.': '多米尼加',
'Algeria': '阿尔及利亚', 'Ecuador': '厄瓜多尔', 'Egypt': '埃及', 'Eritrea': '厄立特里亚', 'Spain': '西班牙',
'Estonia': '爱沙尼亚', 'Ethiopia': '埃塞俄比亚', 'Finland': '芬兰', 'Fiji': '斐济', 'Falkland Is.': '福克兰群岛(马尔维纳斯)',
'France': '法国', 'Faeroe Is.': '法罗群岛', 'Micronesia': '密克罗尼西亚', 'Gabon': '加蓬', 'United Kingdom': '英国',
'Georgia': '格鲁吉亚', 'Ghana': '加纳', 'Guinea': '几内亚', 'Gambia': '冈比亚', 'Guinea-Bissau': '几内亚比绍',
'Eq. Guinea': '赤道几内亚', 'Greece': '希腊', 'Grenada': '格林纳达', 'Greenland': '格陵兰', 'Guatemala': '危地马拉',
'Guam': '关岛', 'Heard I. and McDonald Is.': '赫德岛和麦克唐纳群岛', 'Honduras': '洪都拉斯',
'Croatia': '克罗地亚', 'Haiti': '海地', 'Hungary': '匈牙利', 'Indonesia': '印度尼西亚', 'Isle of Man': '英国属地曼岛',
'India': '印度', 'Br. Indian Ocean Ter.': '英属印度洋领土', 'Ireland': '爱尔兰', 'Iran': '伊朗', 'Iraq': '伊拉克',
'Iceland': '冰岛', 'Israel': '以色列', 'Italy': '意大利', 'Jamaica': '牙买加', 'Jersey': '泽西岛', 'Jordan': '约旦',
'Japan': '日本', 'Siachen Glacier': '锡亚琴冰川', 'Kazakhstan': '哈萨克斯坦', 'Kenya': '肯尼亚',
'Kyrgyzstan': '吉尔吉斯斯坦', 'Cambodia': '柬埔寨', 'Kiribati': '基里巴斯', 'Korea': '韩国', 'Kuwait': '科威特',
'Lao PDR': '老挝', 'Lebanon': '黎巴嫩', 'Liberia': '利比里亚', 'Libya': '利比亚', 'Saint Lucia': '圣卢西亚',
'Sri Lanka': '斯里兰卡', 'Lesotho': '莱索托', 'Lithuania': '立陶宛', 'Luxembourg': '卢森堡', 'Latvia': '拉脱维亚',
'Moldova': '摩尔多瓦', 'Madagascar': '马达加斯加', 'Mexico': '墨西哥', 'Macedonia': '北马其顿', 'Mali': '马里',
'Malta': '马耳他', 'Myanmar': '缅甸', 'Montenegro': '黑山', 'Mongolia': '蒙古', 'N. Mariana Is.': '北马里亚纳',
'Mozambique': '莫桑比克', 'Mauritania': '毛利塔尼亚', 'Montserrat': '蒙特塞拉特', 'Mauritius': '毛里求斯',
'Malawi': '马拉维', 'Malaysia': '马来西亚', 'Namibia': '纳米比亚', 'New Caledonia': '新喀里多尼亚', 'Niger': '尼日尔',
'Nigeria': '尼日利亚', 'Nicaragua': '尼加拉瓜', 'Niue': '纽埃', 'Netherlands': '荷兰', 'Norway': '挪威',
'Nepal': '尼泊尔', 'New Zealand': '新西兰', 'Oman': '阿曼', 'Pakistan': '巴基斯坦', 'Panama': '巴拿马', 'Peru': '秘鲁',
'Philippines': '菲律宾', 'Palau': '帕劳', 'Papua New Guinea': '巴布亚新几内亚', 'Poland': '波兰',
'Puerto Rico': '波多黎各', 'Dem. Rep. Korea': '朝鲜', 'Portugal': '葡萄牙', 'Paraguay': '巴拉圭',
'Palestine': '巴勒斯坦', 'Fr. Polynesia': '法属波利尼西亚', 'Qatar': '卡塔尔', 'Romania': '罗马尼亚', 'Russia': '俄罗斯',
'Rwanda': '卢旺达', 'Saudi Arabia': '沙特阿拉伯', 'Sudan': '苏丹', 'S. Sudan': '南苏丹', 'Senegal': '塞内加尔',
'Singapore': '新加坡', 'S. Geo. and S. Sandw. Is.': '南乔治亚岛和南桑威奇群岛', 'Saint Helena': '圣赫勒拿',
'Solomon Is.': '所罗门群岛', 'Sierra Leone': '塞拉利昂', 'El Salvador': '萨尔瓦多',
'St. Pierre and Miquelon': '圣皮埃尔和密克隆', 'São Tomé and Principe': '圣多美和普林西比', 'Suriname': '苏里南',
'Slovakia': '斯洛伐克', 'Slovenia': '斯洛文尼亚', 'Sweden': '瑞典', 'Swaziland': '斯威士兰', 'Seychelles': '塞舌尔',
'Syria': '叙利亚', 'Turks and Caicos Is.': '特克斯和凯科斯群岛', 'Chad': '乍得', 'Togo': '多哥', 'Thailand': '泰国',
'Tajikistan': '塔吉克斯坦', 'Turkmenistan': '土库曼斯坦', 'Timor-Leste': '东帝汶', 'Tonga': '汤加',
'Trinidad and Tobago': '特立尼达和多巴哥', 'Tunisia': '突尼斯', 'Turkey': '土耳其', 'Tanzania': '坦桑尼亚',
'Uganda': '乌干达', 'Ukraine': '乌克兰', 'Uruguay': '乌拉圭', 'United States': '美国', 'Uzbekistan': '乌兹别克斯坦',
'St. Vin. and Gren.': '圣文森特和格林纳丁斯', 'Venezuela': '委内瑞拉', 'U.S. Virgin Is.': '美属维尔京群岛', 'Vietnam': '越南',
'Vanuatu': '瓦努阿图', 'Samoa': '萨摩亚', 'Yemen': '也门', 'South Africa': '南非', 'Zambia': '赞比亚',
'Zimbabwe': '津巴布韦', 'Somalia': '索马里', "Anguilla": "安圭拉", 'Dominica': '多米尼克','Gibraltar': '直布罗陀',
'Guyana': '圭亚那','Saint Kitts and Nevis': '圣基茨和尼维斯','Monaco': '摩纳哥','Maldives': '马尔代夫','San Marino': '圣马力诺',
'Vatican City': '梵蒂冈','British Virgin Islands': '英属维尔京群岛'}
def get_data():
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 读取数据
df = df.loc[df['province'].isnull()] # 定位到全球国家数据,即province列是nan值
# 每个国家对应的洲dict
continent = {
'亚洲': ['中国', '蒙古', '朝鲜', '韩国', '日本', '菲律宾', '越南', '老挝', '柬埔寨', '缅甸', '泰国', '马来西亚', '文莱', '新加坡', '印度尼西亚', '东帝汶',
'尼泊尔','不丹', '孟加拉国', '印度', '巴基斯坦', '斯里兰卡', '马尔代夫', '哈萨克斯坦', '吉尔吉斯斯坦', '塔吉克斯坦', '乌兹别克斯坦', '土库曼斯坦', '阿富汗',
'伊拉克','伊朗', '北马里亚纳','叙利亚', '约旦', '黎巴嫩', '以色列', '巴勒斯坦', '沙特阿拉伯', '巴林', '卡塔尔', '科威特', '阿联酋', '阿曼', '也门', '格鲁吉亚',
'亚美尼亚','阿塞拜疆','土耳其'],
'欧洲': ['英国', '法国', '荷兰', '爱尔兰', '比利时', '卢森堡', '摩纳哥', '丹麦', '挪威', '瑞典', '芬兰', '冰岛', '罗马尼亚', '保加利亚', '塞尔维亚', '黑山',
'北马其顿', '阿尔巴尼亚', '希腊', '斯洛文尼亚', '克罗地亚', '波黑', '意大利', '梵蒂冈', '圣马力诺', '马耳他', '西班牙', '葡萄牙', '安道尔',
'塞浦路斯', '波兰', '捷克', '斯洛伐克', '奥地利', '匈牙利', '德国', '瑞士', '列支敦士登', '爱沙尼亚', '拉脱维亚', '立陶宛', '白俄罗斯', '俄罗斯',
'乌克兰', '泽西岛','摩尔多瓦', '海峡群岛', '福克兰群岛(马尔维纳斯)', '英国属地曼岛', '圣马丁', '法罗群岛', '直布罗陀'],
'非洲': ['埃及', '利比亚', '突尼斯', '阿尔及利亚', '摩洛哥', '埃塞俄比亚', '厄立特里亚', '索马里', '吉布提', '肯尼亚', '坦桑尼亚', '乌干达', '卢旺达', '布隆迪',
'塞舌尔','苏丹', '南苏丹', '乍得', '中非', '喀麦隆', '赤道几内亚', '加蓬', '刚果(布)', '刚果(金)', '圣多美和普林西比', '毛利塔尼亚', '塞内加尔', '冈比亚',
'马里','布基纳法索', '几内亚', '几内亚比绍', '佛得角', '塞拉利昂', '利比里亚', '科特迪瓦', '加纳', '多哥', '贝宁', '尼日尔', '尼日利亚', '赞比亚', '安哥拉',
'津巴布韦','马拉维', '莫桑比克', '博茨瓦纳', '纳米比亚', '南非', '斯威士兰', '莱索托', '马达加斯加', '科摩罗', '毛里求斯', '马约特', '留尼汪'],
'北美洲': ['加拿大', '美国', '墨西哥', '危地马拉', '伯利兹', '萨尔瓦多', '洪都拉斯', '尼加拉瓜', '哥斯达黎加', '巴拿马', '巴哈马', '古巴', '牙买加', '海地',
'圣皮埃尔和密克隆','多米尼加', '安提瓜和巴布达', '圣基茨和尼维斯', '多米尼克', '圣卢西亚', '圣文森特和格林纳丁斯', '格林纳达', '巴巴多斯', '特立尼达和多巴哥',
'圣皮埃尔', '百慕大','英属维尔京群岛', '安圭拉', '特克斯和凯科斯群岛', '蒙特塞拉特', '格陵兰', '瓜德罗普', '开曼群岛', '阿鲁巴', '库拉索', '圣巴泰勒米岛',
'马提尼克', '波多黎各','美属维尔京群岛'],
'南美洲': ['哥伦比亚', '委内瑞拉', '圭亚那', '苏里南', '厄瓜多尔', '秘鲁', '玻利维亚', '巴西', '智利', '阿根廷', '乌拉圭', '巴拉圭', '法属圭亚那'],
'大洋洲': ['澳大利亚', '新西兰', '帕劳', '密克罗尼西亚联邦', '马绍尔群岛', '基里巴斯', '瑙鲁', '巴布亚新几内亚', '所罗门群岛', '瓦努阿图', '斐济', '图瓦卢', '萨摩亚',
'汤加', '关岛','库克群岛', '纽埃', '新喀里多尼亚', '法属波利尼西亚']
}
def assortment(x): # 定义一个分类函数
for k,v in continent.items():
if x in v:
return k
df['contient'] = df['country'].apply(assortment) # df中添加一列各国对应的大洲名
time_list = df.loc[df['country'] == '中国']['date'].unique().tolist() # 时间列表
data_list = [] # 所有数据列表
for i in time_list:
map_data = []
country_name = df.loc[df['date'] == i]['country'].tolist() # 国家列表
country_confirm_num = df.loc[df['date'] == i]['confirmed'].tolist() # 与国家列表相对应的确诊人数列表
for x,y in zip(country_name,country_confirm_num):
map_data.append({"name":x,"value":[y,x]})
global_confirm_num = df.loc[df['date'] == i].sum()['confirmed'] # 全球确诊人数列表
contient_confirm_num = df.loc[df['date'] == i].groupby('contient').sum()['confirmed'].tolist() # 各大洲确诊人数列表
contient_name = df.loc[df['date'] == i].groupby('contient').sum()['confirmed'].index.tolist() # 大洲名
pie_data = [i for i in zip(contient_name, contient_confirm_num)] # 饼图数据
bar_data = [] # 柱状图数据
df_top25_confirm_country = pd.DataFrame(data=country_confirm_num,index=country_name,columns=['num'])
df_top25_confirm_country = df_top25_confirm_country.sort_values('num',ascending=False).head(25) # 全球确诊数前25位国家与确诊数df
top25_confirm_country= df_top25_confirm_country.index.tolist() # 全球确诊数前25位国家名字列表
top25_confirm_country_num = df_top25_confirm_country['num'].tolist() # 全球确诊数前25位国家确诊数列表
for a,b in zip(top25_confirm_country,top25_confirm_country_num):
bar_data.append({"name":a,"value":b})
data_list.append({"time":i,"data": {"map_data":map_data,"bar_data": {"name":top25_confirm_country,"value":bar_data},"pie_data":pie_data,"line_data":global_confirm_num}})
time_line(data_list,time_list)
def get_day_chart(data,time_list,day):
# global_confirm_num = [i['data']['line_data'] for i in data] # 这么传确诊数据画折线图时有点问题,目前的解决方法是打印出来再放在函数内
global_confirm_num = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 6, 6, 7, 8, 9, 14, 18, 21, 29, 30, 33, 35, 37, 37, 37, 37, 40, 43, 44, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 47, 62, 198, 275, 295, 445, 577, 839, 1305, 1998, 2777, 4556, 6030, 7784, 9777, 11876, 14465, 17290, 20523, 24324, 28018, 31380, 34865, 37453, 40535, 43092, 45128, 59283, 64435, 67091, 69177, 71326, 73331, 75181, 76109, 77089, 77615, 78390, 79153, 80059, 80776, 81718, 82907, 84298, 86274, 87503, 89938, 92473, 94489, 96923, 100787, 104005, 107947, 111475, 116404, 121750, 129206, 139196, 148507, 161895, 174424, 187921, 205334, 229007, 254088, 287385, 318075, 359038, 396304, 439388, 491472, 555936, 620524, 685374, 743479, 809739, 885183, 963547, 1050006, 1154606, 1228703, 1296919, 1376639, 1457146, 1537834, 1627708, 1726067, 1801472, 1871663, 1950795, 2026797, 2117948, 2160870, 2276746, 2363064, 2437346, 2511944, 2594414, 2668783, 2761940, 2866823, 2948982, 3026987, 3092487, 3168018, 3251817, 3342236, 3430121, 3516219, 3595614, 3675262, 3763095, 3856621, 3954198, 4046293, 4135407, 4220903, 4296056, 4378064, 4471726, 4567793, 4665396, 4754391, 4841589, 4928151, 5019712, 5128065, 5232357, 5344240, 5440546, 5536452, 5625886, 5722044, 5828573, 5949338, 6070180, 6201973, 6302943, 6410130, 6528854, 6615088, 6744678, 6894885, 7023370, 7129890, 7240586, 7363639, 7504001, 7644944, 7774961, 7914745, 8036193, 8157051, 8311584, 8440982, 8625327, 8806970, 8965984, 9088717, 9236180, 9402366, 9576377, 9761393, 9959246, 10139301, 10301991, 10463382, 10637573, 10858187, 11042322, 11239529, 11434207, 11612189, 11789840, 12005058, 12220325, 12445327, 12677164, 12895696, 13093522, 13285775, 13517315, 13755265, 14009299, 14253687, 14481482, 14704273, 14921151, 15152108, 15455658, 15732548, 16020885, 16275298, 16501128, 16708041, 16948893, 17242062, 17573340, 17844591, 18089190, 18317797, 18511123, 18787085, 19050863, 19333035, 19612089, 19874305, 20098137, 20335304, 20611420, 20878388, 21138130, 21418432, 21705433, 21897348, 22141369, 22394936, 22674711, 22932805, 23216277, 23447688, 23651995, 23904456, 24138940, 24404401, 24714688, 24993449, 25241808, 25473263, 25733181, 26005959, 26278094, 26562178, 26893408, 27155320, 27378802, 27568865, 27834732, 28121685, 28453449, 28767461, 29026540, 29221414, 29522135, 29804754, 30143923, 30451420, 30798922, 31096846, 31319306]
minNum = 0
maxNum = 7500000 # 国家确诊人数的最大值
map_data = [
[[x["name"], x["value"]] for x in d["data"]["map_data"]] for d in data if d["time"] == day
][0]
map_chart = (
Map()
.add(
series_name="",
data_pair=map_data,
zoom=1,
center=[80, 10],
maptype='world',
name_map=name_map,
is_map_symbol_show=False,
# itemstyle_opts={
# "normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
# "emphasis": {
# "label": {"show": Timeline},
# "areaColor": "rgba(255,255,255, 0.5)",
# },
# },
itemstyle_opts={
"normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
"emphasis": {
"areaColor": "rgba(255,255,255, 0.5)",
},
},
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(
title="全球新冠疫情地图{}".format(time_list[-1]),
subtitle="",
pos_left="center",
pos_top="2%",
title_textstyle_opts=opts.TextStyleOpts(
font_size=25, color="rgba(255,255,255, 0.9)"
),
),
tooltip_opts=opts.TooltipOpts(
is_show=True,
formatter=JsCode(
"""function(params) {
if ('value' in params.data) {
return params.data.value[1] + ': ' + params.data.value[0];
}
}"""
),
),
)
)
data_mark = []
i = 0
for x in time_list:
if x == day:
data_mark.append(global_confirm_num[i])
else:
data_mark.append("")
i = i + 1
line_chart = (
Line()
.add_xaxis(time_list)
.add_yaxis("", global_confirm_num)
.add_yaxis(
"",
data_mark,
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False), )
.set_global_opts(
title_opts=opts.TitleOpts(
title="全球新冠疫情确诊总人数发展趋势", pos_left="72%", pos_top="7%"
),
yaxis_opts=opts.AxisOpts(
is_show=False,
),
)
)
bar_x_data = [d['data']["bar_data"]["name"] for d in data if d["time"] == day][0]
bar_y_data = [d['data']["bar_data"]["value"] for d in data if d["time"] == day][0]
bar = (
Bar()
.add_xaxis(xaxis_data=bar_x_data)
.add_yaxis(
series_name="",
yaxis_data=bar_y_data,
yaxis_index=1,
label_opts=opts.LabelOpts(
is_show=True, position="right", formatter="{b} : {c}"
),
)
.reversal_axis()
.set_global_opts(
xaxis_opts=opts.AxisOpts(max_=maxNum, axislabel_opts=opts.LabelOpts(is_show=False)),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(is_show=False)),
tooltip_opts=opts.TooltipOpts(is_show=False),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True,
is_calculable=True,
dimension=0,
pos_left="10",
pos_top="26%",
pieces=[
{'max': 9, 'min': 0, 'label': '0-9', 'color': '#FFF5EE'},
{'max': 99, 'min': 10, 'label': '10-99', 'color': '#FFE4C4'},
{'max': 999, 'min': 100, 'label': '100-999', 'color': '#FFC4B3'},
{'max': 9999, 'min': 1000, 'label': '1000-9999', 'color': '#FF9985'},
{'max': 99999, 'min': 10000, 'label': '10000-99999', 'color': '#F57567'},
{'max': 499999, 'min': 100000, 'label': '100000-499999', 'color': '#E64546'},
{'max': 999999, 'min': 500000, 'label': '500000-999999', 'color': '#B80909'},
{'max': 4999999, 'min': 1000000, 'label': '1000000-4999999', 'color': '#8A0808'},
{'max': 99999999, 'min': 5000000, 'label': '>=5000000', 'color': '#660000'}
]
),
graphic_opts=[
opts.GraphicGroup(
graphic_item=opts.GraphicItem(
rotation=JsCode("Math.PI / 4"),
bounding="raw",
right=120,
bottom=120,
z=120,
),
children=[
opts.GraphicRect(
graphic_item=opts.GraphicItem(left="center", top="center", z=100),
graphic_shape_opts=opts.GraphicShapeOpts(width=400, height=80),
graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
fill="rgba(0,0,0,0.3)"
),
),
opts.GraphicText(
graphic_item=opts.GraphicItem(left="center", top="center", z=100),
graphic_textstyle_opts=opts.GraphicTextStyleOpts(
text=f"{str(day)}",
font="bold 30px Microsoft YaHei",
graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(fill="#fff"),
),
),
],
)
],
)
)
pie_data = [
d["data"]["pie_data"] for d in data if d["time"] == day
][0]
pie = (
Pie()
.add(
series_name="",
data_pair=pie_data,
radius=["15%", "35%"],
center=["80.5%", "74%"],
label_opts=opts.LabelOpts(formatter="{b}:{d}%", position="outside", font_size=16), # formatter="{b}\n确诊人数:{c}\n占比:{d}%"
itemstyle_opts=opts.ItemStyleOpts(
border_width=1, border_color="rgba(0,0,0,0.3)"
),
)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(is_show=False),
legend_opts=opts.LegendOpts(is_show=False),
)
)
grid_chart = (
Grid()
.add(
bar,
grid_opts=opts.GridOpts(
pos_left="15", pos_right="40%", pos_top="50%", pos_bottom="5"
),
)
.add(
line_chart,
grid_opts=opts.GridOpts(
pos_left="65%", pos_right="5%", pos_top="5", pos_bottom="55%"
),
)
.add(pie, grid_opts=opts.GridOpts())
.add(map_chart, grid_opts=opts.GridOpts()
)
)
return grid_chart
def time_line(data,time_list):
timeline = Timeline(
init_opts=opts.InitOpts(width="2250px", height="1000px", theme=ThemeType.DARK)
)
for d in time_list:
g = get_day_chart(data,time_list,d)
timeline.add(g, time_point=str(d))
timeline.add_schema(
orient="vertical",
is_auto_play=False,
is_inverse=True,
play_interval=500,
pos_left="null",
pos_right="20",
pos_top="20",
pos_bottom="20",
width="60",
label_opts=opts.LabelOpts(is_show=False),#(is_show=True, color="#fff",interval=15),
)
timeline.render("全球疫情发展趋势.html")
if __name__ == "__main__":
get_data()
运行以上代码可得到的图预览:
4.制作词云
#coding:utf-8
import pandas as pd
import numpy as np
from wordcloud import WordCloud
from matplotlib import colors
from PIL import Image
def wordcloude_china():
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 读取数据
city = df.loc[(~df['city'].isnull())&(df['date']=='2020-09-21')]['city'].tolist() # 定位到市区最新数据
confirm_num = df.loc[(~df['city'].isnull())&(df['date']=='2020-09-21')]['confirmed'].tolist()
data = {i:j for i,j in zip(city, confirm_num)}
word_cloud = WordCloud(
font_path='C:/Windows/Fonts/msyhbd.ttc',# 显示中文需要加载本地中文字体
background_color='white', # 设置背景色
width=1000,
height=600)
word_cloud.generate_from_frequencies(data)
word_cloud.to_file('中国疫情词云图.png')
def wordcloude_world():
df = pd.read_csv('Wuhan-2019-nCoV.csv') # 读取数据
country = df.loc[(df['province'].isnull())&(df['date']=='2020-09-21')]['country'].tolist() # 定位到全球国家最新数据
confirm_num = df.loc[(df['province'].isnull())&(df['date']=='2020-09-21')]['confirmed'].tolist()
data = {i:j for i,j in zip(country, confirm_num)}
color_list = ['#CD0000', '#CD3700', '#CD4F39', '#CD5B45', '#CD6600', '#CD8500', '#CD8162', '#CD7054', '#CD3333', '#CD2626', '#CD661D', '#CD853F', '#CDBA96', '#CDAA7D', '#CD6839', '#CD5555', '#CD9B9B', '#CD950C', '#CD9B1D', '#CDAD00', '#CDCD00', '#CDCDB4', '#CDBE70', '#CDC673', '#A2CD5A', '#9ACD32', '#66CD00', '#00CD00', '#00CD66', '#7CCD7C', '#43CD80', '#9BCD9B', '#66CDAA', '#79CDCD', '#00CDCD', '#00C5CD', '#7AC5CD', '#96CDCD', '#EE0000', '#EE4000', '#EE5C42', '#EE6A50', '#EE7600', '#EE9A00', '#EE9572', '#EE8262', '#EE3B3B', '#EE2C2C', '#EE7621', '#EE9A49', '#EED8AE', '#EEC591', '#EE7942', '#EE6363', '#EEB4B4', '#EEAD0E', '#EEB422', '#EEC900', '#EEEE00', '#EEEED1', '#EEDC82', '#EEE685', '#BCEE68', '#B3EE3A', '#76EE00', '#00EE00', '#00EE76', '#90EE90', '#4EEE94', '#B4EEB4', '#76EEC6', '#8DEEEE', '#00EEEE', '#00E5EE', '#8EE5EE', '#AEEEEE', '#FF0000', '#FF4500', '#FF6347', '#FF7256', '#FF7F00', '#FFA500', '#FFA07A', '#FF8C69', '#FF4040', '#FF3030', '#FF7F24', '#FFA54F', '#FFE7BA', '#FFD39B', '#FF8247', '#FF6A6A', '#FFC1C1', '#FFB90F', '#FFC125', '#FFD700', '#FFFF00', '#FFFFE0', '#FFEC8B', '#FFF68F', '#CAFF70', '#C0FF3E', '#7FFF00', '#00FF00', '#00FF7F', '#9AFF9A', '#54FF9F', '#C1FFC1', '#7FFFD4', '#97FFFF', '#00FFFF', '#00F5FF', '#98F5FF', '#BBFFFF', '#8B0000', '#8B2500', '#8B3626', '#8B3E2F', '#8B4500', '#8B5A00', '#8B5742', '#8B4C39', '#8B2323', '#8B1A1A', '#8B4513', '#8B5A2B', '#8B7E66', '#8B7355', '#8B4726', '#8B3A3A', '#8B6969', '#8B658B', '#8B6914', '#8B7500', '#8B8B00', '#8B8B7A', '#8B814C', '#8B864E', '#6E8B3D', '#698B22', '#008B00', '#458B00', '#008B45', '#548B54', '#2E8B57', '#698B69', '#458B74', '#528B8B', '#008B8B', '#00868B', '#53868B', '#668B8B']
colormap = colors.ListedColormap(color_list) # 将自定义的色号转化为wc可用的colormap
mask = np.array(Image.open('mask.jpg')) # 打开本地口罩白底图---可以去淘宝、京东搜索口罩然后找白底图
wc = WordCloud(
font_path='C:/Windows/Fonts/msyhbd.ttc',
background_color='white',
colormap=colormap,
prefer_horizontal=0.8,# 水平显示的文字相对于竖直显示文字的比例
mask=mask,# 添加蒙版
# contour_width=0.1,
# contour_color='green',
relative_scaling=0.3,# 设置字体大小与词频的关联程度为0.3
max_font_size=80,# 设置显示的最大字体
scale = 3,# 提升图片的精细程度,3为放大3倍
max_words = 250, # 显示的最大词语数量
width=1600,
height=1200)
wc.generate_from_frequencies(data)
wc.to_file('全球疫情词云图.png')
if __name__ == '__main__':
wordcloude_china()
wordcloude_world()
可得的词云图如下:
码字不易,若对您有所帮助,望能关注收藏点赞,谢谢
更多推荐
所有评论(0)