wsgxg

python实现每日票房的可视化

  1. 最近有在学人工智能导论这门课程,其中第一个作业是可视化实践,本来老师给的例子是新冠疫情实时地图,基于basemap模块,但是,我在上网查资料学习了之后发现了一个更好的模块——pyecharts

  2. Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。这里面有很多图表、地图等可视化图形,具体的可以上官方演示文档看一看效果。

  3. 官方pyecharts分为 v0.5.X 和 v1 两个大版本,v0.5.X 和 v1 间不兼容,v0.5.X支持 Python2.7,3.4+,v1仅支持 Python3.6+,我的python版本是3.9,所以用v1版本。

  4. 另外,新冠地图在网上分享的代码挺多的,所以我又自己练习了一个每日票房的饼状图和柱状图。json数据来源于某眼电影和ZAKER新闻,先上图:


image


image


接下来直接上代码:

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()

最终的效果如下图:
image

分类:

技术点:

相关文章: