Pyecharts进阶篇

2024-06-28 09:27:01 浏览数 (2)

本章节,我们会使用全国空气质量数据呈现中国地图,还会使用全球各个国家或地区GDP数据绘制全球地图。

全国空气质量分布图

数据准备

代码语言:javascript复制
import pandas as pd
import numpy as np
path = "final_data02.csv"
show_data = pd.read_csv(path)
show_data.head()
代码语言:javascript复制
temp = show_data[['AQI', 'PM2.5细颗粒物',
                         'PM10可吸入颗粒物', 'CO一氧化碳', 'NO2二氧化氮',
                         'O3臭氧1小时平均', 'O3臭氧8小时平均', 'SO2二氧化硫']].head(50)
temp.mean()

#
AQI           58.50
PM2.5细颗粒物     36.24
PM10可吸入颗粒物    55.98
CO一氧化碳         0.79
NO2二氧化氮       21.46
O3臭氧1小时平均     56.08
O3臭氧8小时平均     41.98
SO2二氧化硫       16.08
dtype: float64

代码语言:javascript复制
show_data['time'] = pd.to_datetime(show_data['time'])
show_data['year'] = show_data.time.dt.year
show_data2 = show_data[show_data['year'] ==2021]
grouper = pd.Grouper(key="time", freq="D")
def transfor(x_df):
    # 每一组又分了5个子子组
    return x_df.groupby(grouper).mean()
show_data3 = show_data2[['city', 'time', 'AQI', 'PM2.5细颗粒物',
                         'PM10可吸入颗粒物', 'CO一氧化碳', 'NO2二氧化氮',
                         'O3臭氧1小时平均', 'O3臭氧8小时平均', 'SO2二氧化硫']]
                        .groupby("city").apply(transfor) # 10组

show_data3 = show_data3.reset_index()
需求1 展现数据集中各个城市或者地区的空气质量分布

数据中包含了很多城市,我们可以使用地图来展现对应数据,新的一个图表,但是有了前置的基础知识,地图绘制也会变得很容易,我们可以参考官网提供的案例进行预览与绘制。

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

c = (
    Map()
    .add("商家A", [list(z) for z in zip(Faker.provinces, Faker.values())], "china")
    .set_global_opts(title_opts=opts.TitleOpts(title="Map-基本示例"))
)
c.render_notebook()

这是一个空的地图,并没有显示数据,这个也是Pyecharts的Bug所在,他并没有及时更新这个数据:

代码语言:javascript复制
[list(z) for z in zip(Faker.provinces, Faker.values())]

#
[['广东', 31],
 ['北京', 60],
 ['上海', 59],
 ['江西', 89],
 ['湖南', 29],
 ['浙江', 63],
 ['江苏', 97]]

代码语言:javascript复制
show_temp = [['广东省', 74],
 ['北京市', 86],
 ['上海市', 123],
 ['山东省', 199],
 ['湖南省', 124],
 ['浙江省', 33],
 ['江苏省', 91]]

c = (
    Map()
    .add("商家A",show_temp , "china")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-VisualMap(连续型)"),
        visualmap_opts=opts.VisualMapOpts(max_=200),
    )
                                               
)
c.render_notebook()

省市名称不能使用简称,必须加上省或者市的后缀,还有一点,这个图表是省份地图,我们需要城市地图, → 离开吧,你需要更广阔的世界

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

show_temp = [['济南市', 74],
 ['青岛市', 86],
 ['淄博市', 123],
 ['烟台市', 199],
 ['威海市', 124]
]

c = (
    Map()
    .add(
        "商家A",
        show_temp,
        "china-cities",
        label_opts=opts.LabelOpts(is_show=False),
        is_roam=False
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-中国地图(带城市)"),
        visualmap_opts=opts.VisualMapOpts(),
    )
)
c.render_notebook()

城市数据已经标记出来了,我们可以查看一下数据的结构

代码语言:javascript复制
[list(z) for z in zip(Faker.guangdong_city, Faker.values())]

#
[['汕头市', 117],
 ['汕尾市', 65],
 ['揭阳市', 28],
 ['阳江市', 131],
 ['肇庆市', 104],
 ['广州市', 27],
 ['惠州市', 66]]

不出所料,我们需要添加城市完整名称, 我们发现所有的两张地图的差别就是add方法的第三个参数,那么地图中到底支持哪些地区呢?pyecharts支持的数据存放在pyecharts.datasets.map_filenames.json 中,大家可以在 这里进行预览,json文件中的所有key就是地图类型,比如可以查看一个省的地图,就拿我的家乡来说吧

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

show_temp = [['赤峰市', 74],
 ['通辽市', 86],
 ['呼和浩特', 123],
 ['包头市', 35]]

c = (
    Map()
    .add(
        "商家A",
        show_temp,
        "内蒙古",
        label_opts=opts.LabelOpts(is_show=False),
        is_roam=False
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-中国地图(带城市)"),
        visualmap_opts=opts.VisualMapOpts(),
    )
)
c.render_notebook()

回归正题,我们还是要使用全国城市地图,进行空气质量分局地图的绘制,中国城市地图支持的城市名称我已经整理出来了

代码语言:javascript复制
china_cities = "石家庄市,唐山市,秦皇岛市,邯郸市,邢台市,保定市,张家口市,承德市,沧州市,廊坊市,衡水市,太原市,大同市,阳泉市,长治市,晋城市,朔州市,晋中市,运城市,忻州市,临汾市,吕梁市,呼和浩特市,包头市,乌海市,赤峰市,通辽市,鄂尔多斯市,呼伦贝尔市,巴彦淖尔市,乌兰察布市,兴安盟,锡林郭勒盟,阿拉善盟,沈阳市,大连市,鞍山市,抚顺市,本溪市,丹东市,锦州市,营口市,阜新市,辽阳市,盘锦市,铁岭市,朝阳市,葫芦岛市,长春市,吉林市,四平市,辽源市,通化市,白山市,松原市,白城市,延边朝鲜族自治州,哈尔滨市,齐齐哈尔市,鸡西市,鹤岗市,双鸭山市,大庆市,伊春市,佳木斯市,七台河市,牡丹江市,黑河市,绥化市,大兴安岭地区,南京市,无锡市,徐州市,常州市,苏州市,南通市,连云港市,淮安市,盐城市,扬州市,镇江市,泰州市,宿迁市,杭州市,宁波市,温州市,嘉兴市,湖州市,绍兴市,金华市,衢州市,舟山市,台州市,丽水市,合肥市,芜湖市,蚌埠市,淮南市,马鞍山市,淮北市,铜陵市,安庆市,黄山市,滁州市,阜阳市,宿州市,六安市,亳州市,池州市,宣城市,福州市,厦门市,莆田市,三明市,泉州市,漳州市,南平市,龙岩市,宁德市,南昌市,景德镇市,萍乡市,九江市,新余市,鹰潭市,赣州市,吉安市,宜春市,抚州市,上饶市,济南市,青岛市,淄博市,枣庄市,东营市,烟台市,潍坊市,济宁市,泰安市,威海市,日照市,临沂市,德州市,聊城市,滨州市,菏泽市,郑州市,开封市,洛阳市,平顶山市,安阳市,鹤壁市,新乡市,焦作市,濮阳市,许昌市,漯河市,三门峡市,南阳市,商丘市,信阳市,周口市,驻马店市,济源市,武汉市,黄石市,十堰市,宜昌市,襄阳市,鄂州市,荆门市,孝感市,荆州市,黄冈市,咸宁市,随州市,恩施土家族苗族自治州,仙桃市,潜江市,天门市,神农架林区,长沙市,株洲市,湘潭市,衡阳市,邵阳市,岳阳市,常德市,张家界市,益阳市,郴州市,永州市,怀化市,娄底市,湘西土家族苗族自治州,广州市,韶关市,深圳市,珠海市,汕头市,佛山市,江门市,湛江市,茂名市,肇庆市,惠州市,梅州市,汕尾市,河源市,阳江市,清远市,东莞市,中山市,潮州市,揭阳市,云浮市,南宁市,柳州市,桂林市,梧州市,北海市,防城港市,钦州市,贵港市,玉林市,百色市,贺州市,河池市,来宾市,崇左市,海口市,三亚市,三沙市,儋州市,五指山市,琼海市,文昌市,万宁市,东方市,定安县,屯昌县,澄迈县,临高县,白沙黎族自治县,昌江黎族自治县,乐东黎族自治县,陵水黎族自治县,保亭黎族苗族自治县,琼中黎族苗族自治县,成都市,自贡市,攀枝花市,泸州市,德阳市,绵阳市,广元市,遂宁市,内江市,乐山市,南充市,眉山市,宜宾市,广安市,达州市,雅安市,巴中市,资阳市,阿坝藏族羌族自治州,甘孜藏族自治州,凉山彝族自治州,贵阳市,六盘水市,遵义市,安顺市,毕节市,铜仁市,黔西南布依族苗族自,黔东南苗,黔南布依族苗族自治州,昆明市,曲靖市,玉溪市,保山市,昭通市,丽江市,普洱市,临沧市,楚雄彝族自治州,红河哈尼族彝族自治州,文山壮族苗族自治州,西双版纳傣族自治州,大理白族自治州,德宏傣族景颇族自治州,怒江傈僳族自治州,迪庆藏族自治州,拉萨市,日喀则市,昌都市,林芝市,山南市,那曲市,阿里地区,西安市,铜川市,宝鸡市,咸阳市,渭南市,延安市,汉中市,榆林市,安康市,商洛市,兰州市,嘉峪关市,金昌市,白银市,天水市,武威市,张掖市,平凉市,酒泉市,庆阳市,定西市,陇南市,临夏回族自治州,甘南藏族自治州,西宁市,海东市,海北藏族自治州,黄南藏族自治州,海南藏族自治州,果洛藏族自治州,玉树藏族自治州,海西蒙古族藏族自治州,银川市,石嘴山市,吴忠市,固原市,中卫市,乌鲁木齐市,克拉玛依市,吐鲁番市,哈密市,昌吉回族自治州,博尔塔拉蒙古自治州,巴音郭楞蒙古自治州,阿克苏地区,克孜勒苏柯尔克孜自治州,喀什地区,和田地区,伊犁哈萨克自治州,塔城地区,阿勒泰地区,石河子市,阿拉尔市,图木舒克市,五家渠市,北屯市,铁门关市,双河市,可克达拉市,昆玉市,胡杨河市,北京市,天津市,上海市,重庆市,台湾省,香港特别行政区,澳门特别行政区"
china_cities = china_cities.split(",")
len(china_cities)

代码语言:javascript复制
abnormal_data = {
    "张家港":"苏州市"
}
def add_city(x):
    # 北京 -> 北京市
    # 济南 -> 济南市
    if abnormal_data.get(x):
        return abnormal_data.get(x)
    if (x "市") in china_cities:
        return x "市"
    for normal_city in china_cities:
        if len(x[:-1])>=2 and x[:-1] in normal_city:
            return normal_city
        elif len(x[:-2])>=2 and x[:-2] in normal_city:
            return normal_city
    return "未知"
show_data3.loc[:,"normal_city"] = show_data3.city.apply(add_city)

这个只是一个简单的处理与映射,我们的核心放在了可视化实现上,在现实的业务中,也不会出现这样的城市数据。

我们编写一个函数,接受指定数据集,指定日期,指定指标,然后将对应的数据使用地图进行绘制。

代码语言:javascript复制
def get_per_day_data_show(df, show_date, col_name):
    condition_str = f"time=='{show_date}'"
    show_data = df.query(condition_str)
    c = (
        Map()
        .add(
            ""
            , [list(z) for z in zip(show_data.normal_city.values.tolist(), show_data[col_name].values.tolist())]
            , "china-cities"
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="中国空气质量数据可视化")
        )
    )
    return c

这个地图确实已经绘制出来了,但是,数据好像不太清晰,所以,需要重新修改一个配置

代码语言:javascript复制
def get_per_day_data_show(df, show_date, col_name):
    condition_str = f"time=='{show_date}'"
    show_data = df.query(condition_str)
    c = (
        Map()
        .add(
            ""
            , [list(z) for z in zip(show_data.normal_city.values.tolist(), show_data[col_name].values.tolist())]
            , "china-cities"
            , label_opts=opts.LabelOpts(is_show=False)
            , is_roam=False
            , is_map_symbol_show=False
            , itemstyle_opts=opts.ItemStyleOpts(
                border_color = "rgb(0,0,0,0.3)"
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="中国空气质量数据可视化")
        )
    )
    return c
c = get_per_day_data_show(show_data4_good2,"2021-01-01","AQI")
c.render_notebook()

在Line图中,曾经自定义过对应的tooltip,本次案例需要对原来的模本进行小小的改动,主要是新增了img标签。

代码语言:javascript复制
from pyecharts.commons.utils import JsCode
def get_per_day_data_show(df, show_date, col_name):
    condition_str = f"time=='{show_date}'"
    show_data = df.query(condition_str)
    value_max_ = show_data[col_name].max()
    value_min_ = show_data[col_name].min()
    c = (
        Map()
        .add(
            ""
            , [list(z) for z in zip(show_data.normal_city.values.tolist(), show_data[col_name].values.tolist())]
            , "china-cities"
            , label_opts=opts.LabelOpts(is_show=False)
            , is_roam=False
            , is_map_symbol_show=False
            , itemstyle_opts=opts.ItemStyleOpts(
                border_color = "rgb(0,0,0,0.3)"
            )
            , tooltip_opts=opts.TooltipOpts(
                formatter=JsCode(
                    """
                       function(param){
                            if(!param.data){
                                return;
                            }
                            let temp='';
                            temp  = '<div style="width:auto;height:auto; background: ';
                            temp  = choose_color(param.data.value);
                            temp  = ';"><div style="font-size:12px;color:#ffffff;margin-bottom:8px;display:flex;align-items:center;line-height:1;"><span style="flex:1;text-align:left;">';
                            temp  = format_number_value(param);
                            temp  = '</span><div style="display:inline-block;margin-left:8px;border-radius:6px;width:50px;height:40px;background-color:gray"><img src="';
                            temp  = choose_image(param.data.value);
                            temp  ='" style="width: 100%;height: 100%;"></div></div></div>';
                            return temp;
                       }
                    """
                )
            )
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="中国空气质量数据可视化")
            , visualmap_opts=opts.VisualMapOpts(
                max_=value_max_   100
                , min_=value_min_
            )
            , graphic_opts=opts.GraphicGroup(
                graphic_item=opts.GraphicItem(
                    rotation=JsCode("Math.PI / 4"),
                    bounding="raw",
                    right=100,
                    bottom=110,
                    z=100,
                )
                , children=[
                    opts.GraphicRect(
                         graphic_item=opts.GraphicItem(
                                left="center", top="center", z=100
                            )
                        , graphic_shape_opts=opts.GraphicShapeOpts(
                                width=400, height=50
                            )
                        ,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=show_date
                            ,font="bold 26px Microsoft YaHei"
                            ,graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                                    fill="#fff"
                            ),
                        )
                    )
                ]
            )
        )
    )
    c.add_js_funcs(
    f"""
    let good_image='{aqi_good}';
    let normal_image='{aqi_normal}';
    let less_bad_image='{aqi_less_bad}';
    let bad_image='{aqi_bad}';
    let more_bad_image='{aqi_more_bad}';
    let terrible_image='{aqi_terrible}';
    """
    )
    c.add_js_funcs(
    """
    function choose_image(value){
        if(value<50){
            return good_image;
        }else if(value<100){
            return normal_image;
        }else if(value<150){
            return less_bad_image;
        }else if(value<200){
            return bad_image;
        }else if(value<300){
            return more_bad_image;
        }else{
            return terrible_image;
        }
    };
    function format_number_value(param){
        return  param.data.name ':' Number(param.data.value).toFixed(2)
    }
    function choose_color(value){
        if(value<=50){
            return '#97D560';
        }else if(value<=100){
            return '#FFCF55';
        }else if(value<=150){
            return '#FF8E52';
        }else if(value<=200){
            return '#FF5F66';
        }else if(value<=300){
            return '#A171B2';
        }else{
            return '#915068';
        }
    }
    """
    )
    return c
c = get_per_day_data_show(show_data4_good2,"2021-01-03","AQI")
c.render_notebook()

所以JavaScript对于Pyecharts也是至关重要的,可以绘制更炫彩的图像,

都做到这里了,接下来就让他动起来吧,引入TimeLine

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map, Timeline
days = pd.Series(show_data4_good2.time.value_counts().index.astype("str")).sort_values().tolist()
tl = Timeline()
tl.add_schema(
    play_interval=1000
    , is_auto_play=True
    , is_timeline_show=False
)
for day in days:
    map0 = get_per_day_data_show(show_data4_good2,day,"AQI")
    tl.add(map0, "{}日".format(day))

    
tl.add_js_funcs(
    f"""
    let good_image='{aqi_good}';
    let normal_image='{aqi_normal}';
    let less_bad_image='{aqi_less_bad}';
    let bad_image='{aqi_bad}';
    let more_bad_image='{aqi_more_bad}';
    let terrible_image='{aqi_terrible}';
    """
)
tl.add_js_funcs(
    """
    function choose_image(value){
        if(value<50){
            return good_image;
        }else if(value<100){
            return normal_image;
        }else if(value<150){
            return less_bad_image;
        }else if(value<200){
            return bad_image;
        }else if(value<300){
            return more_bad_image;
        }else{
            return terrible_image;
        }
    };
    function format_number_value(param){
        return  param.data.name ':' Number(param.data.value).toFixed(2)
    }
    function choose_color(value){
        if(value<=50){
            return '#97D560';
        }else if(value<=100){
            return '#FFCF55';
        }else if(value<=150){
            return '#FF8E52';
        }else if(value<=200){
            return '#FF5F66';
        }else if(value<=300){
            return '#A171B2';
        }else{
            return '#915068';
        }
    }
    """
)
tl.render_notebook()
# tl.render("./map02.html")

现在图标显示是变化的了,如果对某一天的数据特别感兴趣,你想查看一下,当你鼠标移入图表的时候,你想暂停移动,这个时候,就需要Js交互了,监听移入事件,就是mouseover事件,监听移出事件,就是mouseout事件,但是TimeLine组件,并不能够真正的暂停,只能移入鼠标的时候,将timeline停止,移出的时候从头开始进行播放,但是需求确定是继续播放,所以,需要记录暂停那个时刻播放的时间节点,再次播放时,需要继续跳转到指定的节点。

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map, Timeline
days = pd.Series(show_data4_good2.time.value_counts().index.astype("str")).sort_values().tolist()
tl = Timeline(
    init_opts=opts.InitOpts(
        chart_id="time"
    )
)
tl.add_schema(
    play_interval=1000
    , is_auto_play=True
    , is_timeline_show=False
)
for day in days[:10]:
    map0 = get_per_day_data_show(show_data4_good2,day,"AQI")
    tl.add(map0, "{}日".format(day))


tl.add_js_funcs(
    """
    let currentIndex = 0;
    chart_time.on("mouseover",(param)=>{
        option_time.baseOption.timeline.autoPlay=false;
        chart_time.setOption(option_time,true)
        chart_time.dispatchAction({type: 'timelineChange',currentIndex: currentIndex})
    });
    chart_time.on("mouseout",(param)=>{
        option_time.baseOption.timeline.autoPlay=true;
        chart_time.setOption(option_time,true)
        chart_time.dispatchAction({type: 'timelineChange',currentIndex: currentIndex})
    });
    chart_time.on('timelinechanged',function(timeLineIndex){
        currentIndex = timeLineIndex.currentIndex;
    })
    """
)
tl.add_js_funcs(
    f"""
    let good_image='{aqi_good}';
    let normal_image='{aqi_normal}';
    let less_bad_image='{aqi_less_bad}';
    let bad_image='{aqi_bad}';
    let more_bad_image='{aqi_more_bad}';
    let terrible_image='{aqi_terrible}';
    """
)
tl.add_js_funcs(
    """
    function choose_image(value){
        if(value<50){
            return good_image;
        }else if(value<100){
            return normal_image;
        }else if(value<150){
            return less_bad_image;
        }else if(value<200){
            return bad_image;
        }else if(value<300){
            return more_bad_image;
        }else{
            return terrible_image;
        }
    };
    function format_number_value(param){
        return  param.data.name ':' Number(param.data.value).toFixed(2)
    }
    function choose_color(value){
        if(value<=50){
            return '#97D560';
        }else if(value<=100){
            return '#FFCF55';
        }else if(value<=150){
            return '#FF8E52';
        }else if(value<=200){
            return '#FF5F66';
        }else if(value<=300){
            return '#A171B2';
        }else{
            return '#915068';
        }
    }
    """
)
tl.render()
需求2 展现世界地图,对GDP数据进行展示

首先需要进行数据处理,本数据集包含世界1960年至2021年各个国家或者地区GDP数值分布,根据之前的经验,数据处理难点还是在国家编号编码处理这里,本实验提供了countries.json文件,该文件中返回地图中需要的标准的国家或地区名称。

代码语言:javascript复制
gdp_path = "./gdp/gdp_clean.csv"
gdp_growth_path = "./gdp/gdp_growth.csv"
pd.set_option('display.float_format', lambda x: '%.2f' % x)
gdp_all =  pd.read_csv(gdp_path)

加载countries.json文件

代码语言:javascript复制
import json
counties_json = "./gdp/countries.json"
counties_json_str = ""
with open(counties_json,'r') as f:
    counties_json_str = f.read()
counties = json.loads(counties_json_str)

def transfer(code):
    en_name = ""
    for obj in counties:
        if obj['iso3'] == code:
            en_name = obj['name']
            return  en_name
    return "未知"
gdp_all['国家或地区英文'] = gdp_all['国家或地区编码'].apply(transfer)

数据处理完毕,接下来就是需要进行可视化,做世界地图也很简答,官方网站也提供了很多的示例,穿越,PiuPiuPiu

代码语言:javascript复制
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

c = (
    Map()
    .add("商家A", [list(z) for z in zip(Faker.country, Faker.values())], "world", is_roam=False)
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-世界地图"),
        visualmap_opts=opts.VisualMapOpts(max_=200),
    )
)
c.render_notebook()

只需要替换数据即可

代码语言:javascript复制
from pyecharts.charts import Map
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode

c = (
    Map()
    .add(
        "商家A"
        , [list(z) for z in zip(gdp_all['国家或地区英文'].tolist()
                                        , gdp_all['2021'].tolist())]
        , "world"
        , is_map_symbol_show = False
        , is_roam=False
        
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False)
                     , tooltip_opts=opts.TooltipOpts(
                            formatter=JsCode(
                                """
                                    function (param){
                                        let show_str = '';
                                        if(param.data.value){
                                            show_str =param.data.name;
                                            show_str =': $' Number(param.data.value).toLocaleString();
                                            return show_str;
                                        }else{
                                            return '';
                                        }
                                    }
                                """
                            )
                        )
                     )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-世界地图"),
        visualmap_opts=opts.VisualMapOpts(max_=gdp_all['2021'].max()),
    )
)
c.render_notebook()

这个是一个定点时间的数据,如果需要让图像轮播,那么我们还需要按时间处理轮播数据。同时,我这里加上了条主图和饼图分别表示该数据。

代码语言:javascript复制
range_color=[
                '#abd9e9',
                '#e0f3f8',
                '#ffffbf',
                '#fee090',
                '#fdae61',
                '#f46d43',
                '#d73027',
                '#a50026'
            ]
def chart(x_data, y_data, data_pair, map_data,year):
    bar = Bar(init_opts=opts.InitOpts(
         theme='light'
    ))
    bar.add_xaxis(
        x_data[::-1]
    )
    bar.add_yaxis(
        '',
        y_data[::-1],
        category_gap='40%',
        label_opts=opts.LabelOpts(
            is_show=True,
            formatter='{c} 亿美元',
            position='insideLeft'),
    )
    bar.set_global_opts(
        xaxis_opts=opts.AxisOpts(is_show=False),
        yaxis_opts=opts.AxisOpts(
            axisline_opts=opts.AxisLineOpts(is_show=False),
            axistick_opts=opts.AxisTickOpts(is_show=False)),
        title_opts=opts.TitleOpts(
            title='GDP TOP20',
            pos_left='2%',
            pos_top='2%',
            title_textstyle_opts=opts.TextStyleOpts(
                color='#00BFFF', font_size=20)
        ),
        visualmap_opts=opts.VisualMapOpts(
            is_show=False,
            max_=(gdp_all['2021']/1e8).max(),
            range_color=range_color
            , is_piecewise=False
            , dimension=0


        ),
        graphic_opts=[
            opts.GraphicGroup(graphic_item=opts.GraphicItem(
                bounding="raw",
                right=200,
                bottom=100,
                z=100),
            # 文字显示区域配置
            children=[
                # 文本设置
                opts.GraphicText(
                    graphic_item=opts.GraphicItem(
                        left="center", top="center", z=100
                    ),
                    graphic_textstyle_opts=opts.GraphicTextStyleOpts(
                        # 要显示的文本
                        text='{}年'.format(year),
                        font="bold 86px Microsoft YaHei",
                        graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
                            fill="rgba(0,0,0,.2)"
                        ),
                    ),
                ),
            ],
        )
        ]
    )
    bar.reversal_axis()

    pie = Pie(init_opts=opts.InitOpts(theme='light', width='200px', height='200px'))
    pie.add(
        "",
        data_pair,
        # 指定饼图中心位置
        center=["25%", "75%"],
        # 将饼图尺寸相应缩小,不然饼图会重叠
        radius=["8%", "18%"],
    )

    pie.set_global_opts(
        legend_opts=opts.LegendOpts(is_show=False),
    )
    pie.set_colors(range_color)

    c = (
        Map()
        .add("", [list(z) for z in zip(map_data["国家或地区英文"].values.tolist()
                                            , (map_data[year]/1e8).values.tolist())]
                                            , "world"
                                            , is_map_symbol_show=False
                                            , zoom=1
                                            , is_roam=False
            )
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False)
                         , tooltip_opts=opts.TooltipOpts(
                                formatter=JsCode(
                                    """
                                        function (param){
                                            let show_str = '';
                                            if(param.data){
                                                show_str =param.data.name;
                                                show_str =': $' Number(param.data.value).toLocaleString();
                                                return show_str;
                                            }else{
                                                return '';
                                            }
                                        }
                                    """
                                )
                            )
                         )
    )


    grid = Grid(init_opts=opts.InitOpts(theme='light', width='1200px', height='800px'))
    bar.overlap(pie)
    grid.add(bar, is_control_axis_index=True, grid_opts=opts.GridOpts(pos_left='5%', pos_right='70%', pos_top='50%', pos_bottom='0%'))
    grid.add(c, is_control_axis_index=False, grid_opts=opts.GridOpts())


    return grid

代码语言:javascript复制
from pyecharts.charts import Map, Timeline, Bar, Pie, Grid
gdp_all_countries = gdp_all.query("国家或地区英文 !='未知'")
gdp_all_countries = gdp_all_countries.fillna(0)
gdp_all_countries = gdp_all_countries.set_index("国家或地区")
def datas_year(df, columns):
    tl = Timeline(init_opts=opts.InitOpts(width="1000px",height="600px"))
    tl.add_schema(
        is_auto_play=True
        , play_interval=1000
        , is_loop_play=False
        , is_timeline_show=False
    )
    for column in columns:
        map_show_data =  gdp_all_countries[['国家或地区英文',column]]
        bar_pie_show_data = map_show_data.sort_values(column,ascending=False).iloc[:20][column]

        data_pair, data_x, data_y = [],[],[]
        pie_data_index = 0
        for name in bar_pie_show_data.index:
            data_x.append(name)
            if name=='中国':
                data_y.append(
                    opts.BarItem(
                        name=name
                        , value=round(bar_pie_show_data[name]/1e8, 0)
                        , itemstyle_opts={
                            # 阴影颜色
                            'shadowColor': 'rgba(255, 0, 0, 0.5)',
                            'shadowBlur': 20,  # 阴影大小
                            'shadowOffsetY': 5,  # Y轴方向阴影偏移
                            'shadowOffsetX': 5,  # x轴方向阴影偏移
                            'borderColor': 'rgba(255, 0, 0, 1)',
                            'borderWidth': 3

                        }
                    )
                )
            else:
                data_y.append(
                    opts.BarItem(
                        name=name,
                        value=round(bar_pie_show_data[name]/1e8, 0),
                        itemstyle_opts={
                            'shadowColor': 'rgba(0, 0, 0, .5)',
                            'shadowBlur': 5,  # 阴影大小
                            'shadowOffsetY': 2,  # Y轴方向阴影偏移
                            'shadowOffsetX': 2,  # x轴方向阴影偏移
                            'borderColor': '#fff'
                        }
                    )
                )
            if pie_data_index<=4:
                data_pair.append(
                    opts.PieItem(
                        name=name
                        , value=round(bar_pie_show_data[name]/1e8, 0)
                        , label_opts=opts.LabelOpts(
                            is_show=True, formatter='{b}n{d}%'
                        )
                    )
                )
            else:
                data_pair.append(
                    opts.PieItem(
                        name=name
                        , value=round(bar_pie_show_data[name]/1e8, 0)
                        , label_opts=opts.LabelOpts(
                            is_show=False, position='inside'
                        )
                    )
                )
            pie_data_index  =1
        c = chart(data_x,data_y,data_pair,map_show_data,column)
        c.load_javascript()
        tl.add(c, "{}年".format(column))
    return tl

代码语言:javascript复制
years = ['1960', '1961', '1962', '1963', '1964', '1965', '1966','1967', '1968', '1969', '1970', '1971', '1972', '1973', '1974', '1975','1976', '1977', '1978', '1979', '1980', '1981', '1982', '1983', '1984','1985', '1986', '1987', '1988', '1989', '1990', '1991', '1992', '1993','1994', '1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002','2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011','2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020','2021']

tl = datas_year(gdp_all_countries, years)
tl.render_notebook()

0 人点赞