python实现每日票房的可视化
-
最近有在学人工智能导论这门课程,其中第一个作业是可视化实践,本来老师给的例子是新冠疫情实时地图,基于basemap模块,但是,我在上网查资料学习了之后发现了一个更好的模块——pyecharts。
-
Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。这里面有很多图表、地图等可视化图形,具体的可以上官方演示文档看一看效果。
-
官方pyecharts分为 v0.5.X 和 v1 两个大版本,v0.5.X 和 v1 间不兼容,v0.5.X支持 Python2.7,3.4+,v1仅支持 Python3.6+,我的python版本是3.9,所以用v1版本。
-
另外,新冠地图在网上分享的代码挺多的,所以我又自己练习了一个每日票房的饼状图和柱状图。json数据来源于某眼电影和ZAKER新闻,先上图:
接下来直接上代码:
import json
import requests
from pyecharts import options as opts
from pyecharts.charts import Page, Map, Map3D, Pie, Bar
from pyecharts.commons.utils import JsCode
from pyecharts.globals import ChartType
def mapmoviespie() -> Pie:
header = {
\'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36\'
}
url = \'http://pf.maoyan.com/getBoxList?date=1&isSplit=true\'
response = requests.get(url, header).text
resp = json.loads(response) # 使用变量resp来接收字典格式的数据
map_version = {} # 定义空字典
i=0 #定义计数变量
list_map = resp[\'boxOffice\'][\'data\']
for data in list_map[\'list\']: # 遍历提取票房数据
name = data[\'movieInfo\'][\'movieName\'] # 电影名称
value = data[\'boxDesc\'] # 电影票房
if i < 20:
map_version[name] = value # 传入字典
else:
break
i=i+1
element = list(map_version.items()) # 将字典值调整为可以传入格式
# print(element)
c = (
Pie(opts.InitOpts(width="1000px", height="800px"))
.add(
"",
# 系列数据项,格式为[(key1,value1),(key2,value2)]
data_pair=element,
# 饼图的圆心,第一项是相对于容器的宽度,第二项是相对于容器的高度
center=["50%", "50%"],
)
.set_global_opts(
title_opts=opts.TitleOpts(title="日实时票房,数据来源于猫眼数据", subtitle="单位:万元"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
return c
def mapmoviesbar() -> Bar:
header = {
\'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36\'
}
url = \'http://pf.maoyan.com/getBoxList?date=1&isSplit=true\'
response = requests.get(url, header).text
resp = json.loads(response) # 使用变量resp来接收字典格式的数据
map_version = {} # 定义空字典
i = 0 # 定义计数变量
names = []
values = []
list_map = resp[\'boxOffice\'][\'data\']
for data in list_map[\'list\']: # 遍历提取票房数据
name = data[\'movieInfo\'][\'movieName\'] # 电影名称
value = data[\'boxDesc\'] # 电影票房
if i < 20:
names.append(name)
values.append(value) #
else:
break
i = i + 1
c = (
Bar()
.add_xaxis(names)
# y轴显示数量
.add_yaxis("日票房", values)
.set_global_opts(title_opts=opts.TitleOpts(title="日实时票房,数据来源于猫眼数据", subtitle="单位:万元"))
)
return c
def mapchina() -> Map:
url = \'http://zkapi.myzaker.com/2019ncov/ncov_track_api.php\'
response = requests.post(url).text
# print(response)
resp = json.loads(response) # 使用变量resp来接收字典格式的数据
# print(resp)
map_version = {} # 定义空字典
global ncov_national_map
ncov_national_map = resp[\'data\']
for data in ncov_national_map[\'ncov_national_map\']: # 遍历提取每个省的疫情数据
name = data[\'name\'] # 省名
value = data[\'value\'] # 该省疫情人数
map_version[name] = int(value) # 将国家和人数以键值对的形式传入字典
element = list(map_version.items()) # 将字典值调整为可以传入地图的格式
# print(element)
c = (
Map(opts.InitOpts(bg_color="#87CEFA",page_title=\'中国疫情分布图\'))
.add(series_name="中国疫情分布图", # 名称
data_pair=element, # 传入数据
is_map_symbol_show=False, # 不显示标记
maptype=\'china\', # 地图类型
)
# 设置全局配置项
.set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=1100000, is_piecewise=True, pieces=[
# {"min": 500000},
{"min": 1000, "max": 99999, "label": \'感染人数:1000-99999人\', "color": "#8B1A1A"},
{"min": 500, "max": 999, "label": \'感染人数:500-999人\', "color": "#EE2C2C"},
{"min": 100, "max": 499, "label": \'感染人数:100-499人\', "color": "#FF7F24"},
{"min": 10, "max": 99, "label": \'感染人数:10-99人\', "color": "#FFA54F"},
{"max": 9, "label": \'感染人数:1-9人\', "color": "#FFE7BA"}, ]),tooltip_opts=opts.TooltipOpts(
# 是否显示提示框
is_show=True,
# 触发类型。可选:
# \'item\': 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
# \'axis\': 坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
# \'none\': 什么都不触发
trigger=\'item\',
# 触发事件:\'mousemove\' 或 \'click\'或 \'mousemove|click\' 或 \'none\'
trigger_on=\'mousemove|click\',
# 指示器类型。可选
# \'line\':直线指示器
# \'shadow\':阴影指示器
# \'none\':无指示器
# \'cross\':十字准星指示器。其实是种简写,表示启用两个正交的轴的 axisPointer。
axis_pointer_type=\'cross\',
# 提示框样式配置
background_color="rgba(0,23,11,0.1)",
border_color=\'white\',
border_width=3,
textstyle_opts=opts.TextStyleOpts(font_size=20),
formatter=\'累计感染人数:{c}\',
))
# 设置系列配置项
.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 不显示各省名
)
return c
def mapworld() -> Map:
url = \'https://api.inews.qq.com/newsqa/v1/automation/foreign/country/ranklist\'
response = requests.post(url).text
resp = json.loads(response) # 使用变量resp来接收字典格式的数据
map_version = {} # 定义空字典
for data in resp[\'data\']: # 遍历提取每个国家的疫情数据
name = data[\'name\'] # 国家名
confirm = data[\'confirm\'] # 该国家疫情人数
map_version[name] = int(confirm) # 将国家和人数以键值对的形式传入字典
element = list(map_version.items()) # 将字典值调整为可以传入地图的格式
name_map = {
\'Singapore Rep.\': \'新加坡\',
\'Dominican Rep.\': \'多米尼加\',
\'Palestine\': \'巴勒斯坦\',
\'Bahamas\': \'巴哈马\',
\'Timor-Leste\': \'东帝汶\',
\'Afghanistan\': \'阿富汗\',
\'Guinea-Bissau\': \'几内亚比绍\',
"Côte d\'Ivoire": \'科特迪瓦\',
\'Siachen Glacier\': \'锡亚琴冰川\',
"Br. Indian Ocean Ter.": \'英属印度洋领土\',
\'Angola\': \'安哥拉\',
\'Albania\': \'阿尔巴尼亚\',
\'United Arab Emirates\': \'阿联酋\',
\'Argentina\': \'阿根廷\',
\'Armenia\': \'亚美尼亚\',
\'French Southern and Antarctic Lands\': \'法属南半球和南极领地\',
\'Australia\': \'澳大利亚\',
\'Austria\': \'奥地利\',
\'Azerbaijan\': \'阿塞拜疆\',
\'Burundi\': \'布隆迪\',
\'Belgium\': \'比利时\',
\'Benin\': \'贝宁\',
\'Burkina Faso\': \'布基纳法索\',
\'Bangladesh\': \'孟加拉国\',
\'Bulgaria\': \'保加利亚\',
\'The Bahamas\': \'巴哈马\',
\'Bosnia and Herz.\': \'波斯尼亚和黑塞哥维那\',
\'Belarus\': \'白俄罗斯\',
\'Belize\': \'伯利兹\',
\'Bermuda\': \'百慕大\',
\'Bolivia\': \'玻利维亚\',
\'Brazil\': \'巴西\',
\'Brunei\': \'文莱\',
\'Bhutan\': \'不丹\',
\'Botswana\': \'博茨瓦纳\',
\'Central African Rep.\': \'中非\',
\'Canada\': \'加拿大\',
\'Switzerland\': \'瑞士\',
\'Chile\': \'智利\',
\'China\': \'中国\',
\'Ivory Coast\': \'象牙海岸\',
\'Cameroon\': \'喀麦隆\',
\'Dem. Rep. Congo\': \'刚果民主共和国\',
\'Congo\': \'刚果\',
\'Colombia\': \'哥伦比亚\',
\'Costa Rica\': \'哥斯达黎加\',
\'Cuba\': \'古巴\',
\'N. Cyprus\': \'北塞浦路斯\',
\'Cyprus\': \'塞浦路斯\',
\'Czech Rep.\': \'捷克\',
\'Germany\': \'德国\',
\'Djibouti\': \'吉布提\',
\'Denmark\': \'丹麦\',
\'Algeria\': \'阿尔及利亚\',
\'Ecuador\': \'厄瓜多尔\',
\'Egypt\': \'埃及\',
\'Eritrea\': \'厄立特里亚\',
\'Spain\': \'西班牙\',
\'Estonia\': \'爱沙尼亚\',
\'Ethiopia\': \'埃塞俄比亚\',
\'Finland\': \'芬兰\',
\'Fiji\': \'斐\',
\'Falkland Islands\': \'福克兰群岛\',
\'France\': \'法国\',
\'Gabon\': \'加蓬\',
\'United Kingdom\': \'英国\',
\'Georgia\': \'格鲁吉亚\',
\'Ghana\': \'加纳\',
\'Guinea\': \'几内亚\',
\'Gambia\': \'冈比亚\',
\'Guinea Bissau\': \'几内亚比绍\',
\'Eq. Guinea\': \'赤道几内亚\',
\'Greece\': \'希腊\',
\'Greenland\': \'格陵兰\',
\'Guatemala\': \'危地马拉\',
\'French Guiana\': \'法属圭亚那\',
\'Guyana\': \'圭亚那\',
\'Honduras\': \'洪都拉斯\',
\'Croatia\': \'克罗地亚\',
\'Haiti\': \'海地\',
\'Hungary\': \'匈牙利\',
\'Indonesia\': \'印度尼西亚\',
\'India\': \'印度\',
\'Ireland\': \'爱尔兰\',
\'Iran\': \'伊朗\',
\'Iraq\': \'伊拉克\',
\'Iceland\': \'冰岛\',
\'Israel\': \'以色列\',
\'Italy\': \'意大利\',
\'Jamaica\': \'牙买加\',
\'Jordan\': \'约旦\',
\'Japan\': \'日本\',
\'Kazakhstan\': \'哈萨克斯坦\',
\'Kenya\': \'肯尼亚\',
\'Kyrgyzstan\': \'吉尔吉斯斯坦\',
\'Cambodia\': \'柬埔寨\',
\'Korea\': \'韩国\',
\'Kosovo\': \'科索沃\',
\'Kuwait\': \'科威特\',
\'Lao PDR\': \'老挝\',
\'Lebanon\': \'黎巴嫩\',
\'Liberia\': \'利比里亚\',
\'Libya\': \'利比亚\',
\'Sri Lanka\': \'斯里兰卡\',
\'Lesotho\': \'莱索托\',
\'Lithuania\': \'立陶宛\',
\'Luxembourg\': \'卢森堡\',
\'Latvia\': \'拉脱维亚\',
\'Morocco\': \'摩洛哥\',
\'Moldova\': \'摩尔多瓦\',
\'Madagascar\': \'马达加斯加\',
\'Mexico\': \'墨西哥\',
\'Macedonia\': \'马其顿\',
\'Mali\': \'马里\',
\'Myanmar\': \'缅甸\',
\'Montenegro\': \'黑山\',
\'Mongolia\': \'蒙古\',
\'Mozambique\': \'莫桑比克\',
\'Mauritania\': \'毛里塔尼亚\',
\'Malawi\': \'马拉维\',
\'Malaysia\': \'马来西亚\',
\'Namibia\': \'纳米比亚\',
\'New Caledonia\': \'新喀里多尼亚\',
\'Niger\': \'尼日尔\',
\'Nigeria\': \'尼日利亚\',
\'Nicaragua\': \'尼加拉瓜\',
\'Netherlands\': \'荷兰\',
\'Norway\': \'挪威\',
\'Nepal\': \'尼泊尔\',
\'New Zealand\': \'新西兰\',
\'Oman\': \'阿曼\',
\'Pakistan\': \'巴基斯坦\',
\'Panama\': \'巴拿马\',
\'Peru\': \'秘鲁\',
\'Philippines\': \'菲律宾\',
\'Papua New Guinea\': \'巴布亚新几内亚\',
\'Poland\': \'波兰\',
\'Puerto Rico\': \'波多黎各\',
\'Dem. Rep. Korea\': \'朝鲜\',
\'Portugal\': \'葡萄牙\',
\'Paraguay\': \'巴拉圭\',
\'Qatar\': \'卡塔尔\',
\'Romania\': \'罗马尼亚\',
\'Russia\': \'俄罗斯\',
\'Rwanda\': \'卢旺达\',
\'W. Sahara\': \'西撒哈拉\',
\'Saudi Arabia\': \'沙特阿拉伯\',
\'Sudan\': \'苏丹\',
\'S. Sudan\': \'南苏丹\',
\'Senegal\': \'塞内加尔\',
\'Solomon Is.\': \'所罗门群岛\',
\'Sierra Leone\': \'塞拉利昂\',
\'El Salvador\': \'萨尔瓦多\',
\'Somaliland\': \'索马里兰\',
\'Somalia\': \'索马里\',
\'Serbia\': \'塞尔维亚\',
\'Suriname\': \'苏里南\',
\'Slovakia\': \'斯洛伐克\',
\'Slovenia\': \'斯洛文尼亚\',
\'Sweden\': \'瑞典\',
\'Swaziland\': \'斯威士兰\',
\'Syria\': \'叙利亚\',
\'Chad\': \'乍得\',
\'Togo\': \'多哥\',
\'Thailand\': \'泰国\',
\'Tajikistan\': \'塔吉克斯坦\',
\'Turkmenistan\': \'土库曼斯坦\',
\'East Timor\': \'东帝汶\',
\'Trinidad and Tobago\': \'特里尼达和多巴哥\',
\'Tunisia\': \'突尼斯\',
\'Turkey\': \'土耳其\',
\'Tanzania\': \'坦桑尼亚\',
\'Uganda\': \'乌干达\',
\'Ukraine\': \'乌克兰\',
\'Uruguay\': \'乌拉圭\',
\'United States\': \'美国\',
\'Uzbekistan\': \'乌兹别克斯坦\',
\'Venezuela\': \'委内瑞拉\',
\'Vietnam\': \'越南\',
\'Vanuatu\': \'瓦努阿图\',
\'West Bank\': \'西岸\',
\'Yemen\': \'也门\',
\'South Africa\': \'南非\',
\'Zambia\': \'赞比亚\',
\'Zimbabwe\': \'津巴布韦\',
\'Comoros\': \'科摩罗\'
}
c = (
Map(opts.InitOpts(bg_color="#87CEFA", page_title=\'世界疫情分布\'))
.add(series_name="世界疫情分布图", # 名称
data_pair=element, # 传入数据
is_map_symbol_show=False, # 不显示标记
maptype=\'world\', # 地图类型
name_map=name_map,
)
# 设置全局配置项
.set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=1100000, is_piecewise=True, pieces=[
{"min": 500000, "label": \'感染人数:49999人以上\', "color": "#8B1A1A"},
{"min": 200000, "max": 499999, "label": \'感染人数:200000-499999人\', "color": "#EE2C2C"},
{"min": 100000, "max": 199999, "label": \'感染人数:100000-199999人\', "color": "#FF7F24"},
{"min": 50000, "max": 99999, "label": \'感染人数:50000-99999人\', "color": "#FFA54F"},
{"min": 10000, "max": 49999, "label": \'感染人数:10000-49999人\', "color": "#FFE7BA"},
{"max": 9999, "label": \'感染人数:10000人以下\', "color": "#F5F5DC"}, ]),tooltip_opts=opts.TooltipOpts(
# 是否显示提示框
is_show=True,
# 触发类型。可选:
# \'item\': 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
# \'axis\': 坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。
# \'none\': 什么都不触发
trigger=\'item\',
# 触发事件:\'mousemove\' 或 \'click\'或 \'mousemove|click\' 或 \'none\'
trigger_on=\'mousemove|click\',
# 指示器类型。可选
# \'line\':直线指示器
# \'shadow\':阴影指示器
# \'none\':无指示器
# \'cross\':十字准星指示器。其实是种简写,表示启用两个正交的轴的 axisPointer。
axis_pointer_type=\'cross\',
# 提示框样式配置
background_color="rgba(0,23,11,0.1)",
border_color=\'white\',
border_width=3,
textstyle_opts=opts.TextStyleOpts(font_size=20),
formatter=\'累计感染人数:{c}\',
))
# 设置系列配置项
.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 不显示国家名
)
return c
def mapchina3D() -> Map3D:
dicts_all = {\'黑龙江\': [127.9688, 45.368], \'上海\': [121.4648, 31.2891],
\'内蒙古\': [110.3467, 41.4899], \'吉林\': [125.8154, 44.2584],
\'辽宁\': [123.1238, 42.1216], \'河北\': [114.4995, 38.1006],
\'天津\': [117.4219, 39.4189], \'山西\': [112.3352, 37.9413],
\'陕西\': [109.1162, 34.2004], \'甘肃\': [103.5901, 36.3043],
\'宁夏\': [106.3586, 38.1775], \'青海\': [101.4038, 36.8207],
\'新疆\': [87.9236, 43.5883], \'西藏\': [91.11, 29.97],
\'四川\': [103.9526, 30.7617], \'重庆\': [108.384366, 30.439702],
\'山东\': [117.1582, 36.8701], \'河南\': [113.4668, 34.6234],
\'江苏\': [118.8062, 31.9208], \'安徽\': [117.29, 32.0581],
\'湖北\': [114.3896, 30.6628], \'浙江\': [119.5313, 29.8773],
\'福建\': [119.4543, 25.9222], \'江西\': [116.0046, 28.6633],
\'湖南\': [113.0823, 28.2568], \'贵州\': [106.6992, 26.7682],
\'广西\': [108.479, 23.1152], \'海南\': [110.3893, 19.8516],
\'广东\': [113.28064, 23.125177], \'北京\': [116.405289, 39.904987],
\'云南\': [102.71225, 25.040609], \'香港\': [114.165460, 22.275340],
\'澳门\': [113.549130, 22.198750], \'台湾\': [121.5200760, 25.0307240]}
for data in ncov_national_map[\'ncov_national_map\']: #遍历提取每个省的疫情数据
name = data[\'name\'] #省名
value = int(data[\'value\']) #该省疫情人数
dicts_all[name].append(value)
c =(
Map3D()
.add_schema(
itemstyle_opts=opts.ItemStyleOpts(
color="rgb(5,101,123)",
opacity=1,
border_width=0.8,
border_color="rgb(62,215,213)"),
map3d_label=opts.Map3DLabelOpts(
is_show=False,
formatter=JsCode(
"function(data){return data.value[2];}")),
emphasis_label_opts=opts.LabelOpts(
is_show=False,
color="#fff",
font_size=10,
background_color="rgba(0,23,11,0.1)"),
light_opts=opts.Map3DLightOpts(
main_color="#fff",
main_intensity=1.2,
main_shadow_quality="high",
is_main_shadow=False,
main_beta=10,
ambient_intensity=0.3),
environment=\'#87CEFA\',
)
.add(
series_name="中国疫情分布图",
data_pair=list(zip(list(dicts_all.keys()), list(dicts_all.values()))),
type_=ChartType.BAR3D,
bar_size=1,
shading="lambert",
label_opts=opts.LabelOpts(
is_show=False,
formatter=JsCode(
"function(data){return data.value[2];}")),
)
# 设置全局配置项
.set_global_opts(visualmap_opts=opts.VisualMapOpts(max_=1100000, is_piecewise=True, pieces=[
# {"min": 500000},
{"min": 1000, "max": 99999, "label": \'感染人数:1000-99999人\', "color": "#8B1A1A"},
{"min": 500, "max": 999, "label": \'感染人数:500-999人\', "color": "#EE2C2C"},
{"min": 100, "max": 499, "label": \'感染人数:100-499人\', "color": "#FF7F24"},
{"min": 10, "max": 99, "label": \'感染人数:10-99人\', "color": "#FFA54F"},
{"max": 9, "label": \'感染人数:1-9人\', "color": "#FFE7BA"}, ]))
)
return c
def page_simple_layout():
page = Page(layout=Page.SimplePageLayout)
page.add(
mapmoviespie(),
mapmoviesbar(),
mapchina(),
mapworld(),
mapchina3D(),
)
page.render("可视化实践.html")
if __name__ == "__main__":
page_simple_layout()
最终的效果如下图: