19

pyecharts绘制复联超级英雄战斗力

 4 years ago
source link: https://zhuanlan.zhihu.com/p/180226942
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

pyecharts绘制复联超级英雄战斗力

上海交通大学 计算机应用技术硕士

前几天在网上看到有人用 matplotlib 绘制了漫威里几大英雄的战斗力图,赶脚灰常有意思。作为漫威和 python 的双重粉丝,我这次又 hold 不住了,于是也做了一个 pyecharts 版的实力对比图,在这里分享给大家。

首先放上一张静态图。

v2-96e6cc118a3f9b6c560b18fbf32a72bf_720w.jpg图1. 复联超级英雄能力对比

这次我绘制的这个图和网上 matplotlib 版本的图有以下区别:

  1. 加入了交互功能,可以查看任意一个英雄的数值,真正做到“想点哪里点哪里”(妈妈再也不用担心我的学习了)
  2. 将多个英雄的图放在一个图表里,方便对比,同时也可以单独查看某个英雄数值
  3. 加入了图片背景,体现作为漫威粉丝的B格

不多说,show you the code!

首先还是导入各种功能模块。opts(options)是 pyecharts 中设置图片详细格式的模块,Radar 是绘制雷达图的类名,因为绘制超级英雄的战斗力(包含多个数值),用雷达图比较适合,JsCode 是 pyecharts 中执行 JavaScript 代码的一个类。

from pyecharts import options as opts
from pyecharts.charts import Radar
from pyecharts.commons.utils import JsCode

接下来是设置各个超级英雄的战斗力数值,这次的战斗力数值来自于百度百科:https://baike.baidu.com/item/%E6%BC%AB%E5%A8%81%E4%BA%BA%E7%89%A9%E8%83%BD%E5%8A%9B%E6%95%B0%E5%80%BC/17935032

我们选取复联六巨头的战斗力数值(美国队长、钢铁侠、黑寡妇、鹰眼、绿巨人以及雷神),数值内容并不多,主要代码如下所示:

captain_america = [{"value": [4, 4, 4, 4, 1, 7], "name": "美国队长"}]
iron_man= [{"value": [6, 3, 5, 3, 5, 3], "name": "钢铁侠"}]
black_widow = [{"value": [3, 3, 2, 3, 2, 7], "name": "黑寡妇"}]
hawkeye = [{"value": [3, 3, 3, 2, 3, 7], "name": "鹰眼"}]
hulk = [{"value": [2, 7, 3, 7, 1, 3], "name": "绿巨人"}]
thor =  [{"value": [2, 7, 6, 7, 7, 6], "name": "雷神"}]

这6个人的数值都用他们各自的英文名作变量名,每个变量是一个 list,里面包含一个 dict,dict 中 value 就代表了每个人的战斗力数值,其同样是一个 list,包含6个数据:智力、力量、速度、耐力、能量发射和战斗技能。后面的 name 则是每个人的中文名,实际上 name 在整个代码中并没有什么作用,只方便显示。

接下来是一个名为 myschema 的变量,是一个 list,里面包含6个 dict,每个 dict 包含3个 key,这6个 dict 主要用来设置雷达图的坐标轴,后面会详细说明。

myschema = [
    {"name": '智力', "max": 7, "min": 0},
    {"name": '力量', "max": 7, "min": 0},
    {"name": '速度', "max": 7, "min": 0},
    {"name": '耐力', "max": 7, "min": 0},
    {"name": '能量发射', "max": 7, "min": 0},
    {"name": '战斗技能', "max": 7, "min": 0}
]

然后就开始我们的主要绘图部分。首先生成一个 Radar 类的实例 r,在这里我们设置了图表的背景图,用到的是 opts.InitOpts 中的 bg_color 属性,其值为

{"type": "pattern", "image": JsCode("img"), "repeat": "no-repeat"}

"type": "pattern" 表示我们用图片作背景,"image": JsCode("img") 表示我们用 JavaScript 代码来设置这个背景图,"repeat": "no-repeat" 表示图片不重复。而 add_js_funcs 方法就是执行相关的 JavaScript 代码,这里的 JavaScript 代码也很简单,就设置一个名为 img 的变量,指定一下路径。在这里我们用的图片是本地图片,名为 a5.png,我们要把这个图片放在自己的当前工作目录下,不知道当前工作目录的可以执行下面的代码查看:

import os
root = os.getcwd()
print(root)

当然这里我们也可以用网上的图片,只要把 img.src 设置为图片的网址就OK了。

r = Radar(init_opts=opts.InitOpts(
            bg_color={"type": "pattern", "image": JsCode("img"), "repeat": "no-repeat"}
        )
) #初始化雷达图
r.add_js_funcs(
    """
    var img = new Image(); img.src = 'a5.png';
    """
) #执行js代码

接下来是一个长长的 chaining methods(方法链),虽然内容多了点,但不少都是重复性代码,所以并不难理解,这里介绍一下里面的主要部分。

add_schema 方法就是设置我们的雷达图,参数 schema 设置为 myschema,就是前面我们提到过的那个 list,里面有6个 dict,每个 dict 就是一个径向轴,dict 的 name 就是径向轴的标签,min 和 max 设置径向轴的最小和最大值。shape 是雷达图的形状,这里设置为圆形,也可以设置为多边形 polygon。center=["50%", "50%"] 表示雷达图的中心在当前绘图区域的中点位置,即当前绘图区域的高度和宽度的50%位置,radius="80%" 表示雷达图的半径为当前绘图区域的大小的80%,即这个区域的宽度和高度中的较小者的80%。angleaxis_opts 参数是用来设置角度坐标轴,其2个参数 axistick_opts、axislabel_opts 全都设为不显示,他们的分别代表了角度轴的刻度、标签,大家可以试试把这些参数设置为 True 的结果。然后是参数 radiusaxis_opts,其用来设置径向轴,其最小值为0,最大值为7,间隔为1,其包含的 splitarea_opts 参数用来设置间隔区域,也就是图中灰色的部分。而 polar_opts 参数则是设置这个雷达图的相关属性,这里我们全部采用默认设置。而 add_schema 的另外两个参数 splitline_opt 和 textstyle_opts 则分别用来设置径向轴的分割线和图中文字,这里我们把分割线设为不显示,文章颜色设为黑色。

r 的 add 方法则用来向图中添加数据,每个 add 方法会添加一个数据,因为我们一共有6个超级英雄,所以用了6次 add 方法。add 方法中 series_name 用来设置数据序列的名称,这也就是图中上面一排圆圈后面的文字,data 是所要输入的数据,areastyle_opts 用来设置每个数据序列图形区域的属性,这里把每个图形区域的不透明度设为0.1,linestyle_opts 设置图形连线的属性,这里把线宽设为1。set_global_opt 则用来设置整个图表的属性,这里我们设置图的标题为"复联六巨头实力对比"。最后我们用 render 生成一个网页。

(
    r.add_schema( #设置雷达图的各种属性
        schema=myschema,
        shape="circle",
        center=["50%", "50%"], #图片中心位置
        radius="80%", #雷达图半径大小
        angleaxis_opts=opts.AngleAxisOpts(
            axistick_opts=opts.AxisTickOpts(is_show=False),
            axislabel_opts=opts.LabelOpts(is_show=False),
        ),
        radiusaxis_opts=opts.RadiusAxisOpts(
            min_=0,
            max_=7,
            interval=1,
            splitarea_opts=opts.SplitAreaOpts(
                is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
            )
        ),
 polar_opts=opts.PolarOpts(),
        splitline_opt=opts.SplitLineOpts(is_show=False),
        textstyle_opts=opts.TextStyleOpts(color="black"),
    )
    .add(
        series_name="美国队长",
        data=captain_america,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .add(
        series_name="钢铁侠",
        data=iron_man,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .add(
        series_name="黑寡妇",
        data=black_widow,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .add(
        series_name="鹰眼",
        data=hawkeye,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .add(
        series_name="绿巨人",
        data=hulk,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .add(
        series_name="雷神",
        data=thor,
        areastyle_opts=opts.AreaStyleOpts(opacity=0.1),
        linestyle_opts=opts.LineStyleOpts(width=1),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="复联六巨头实力对比")
    )
    .render('ht1.html')
)

生成的结果如图2所示:

v2-5af96761d854b3eb7200ea8fde1cda1d_b.jpg
图2. 生成的动态效果图

在我们绘制的图中,如果想只查看某个英雄的数值,我们则可以单击其他英雄的序列名称,就是图中上面那一排小圆圈和后面的文字,每次单击就会使这个英雄的名称变成灰色,其代表的图形也会在图中消失,再次单击则会复原,这样就会只留下我们需要的英雄的数值。如图3所示,我们只留下绿巨人的图:

图3. 绿巨人战斗力图

pyecharts 的优点是绘图快、交互设计好,它提供了很多 matplotlib 不具备或很难实现的功能,这给我们在绘制交互式图表时提供了更好的选择。本文所有图片和代码都已上传,如有需要可自行下载:

https://gitee.com/crossin/snippet/tree/master/marvel-radar

作者简介:小李子(tyrant100),数据分析爱好者,擅长数据可视化,比较关注机器学习领域,希望能和业内朋友多学习交流。

获取更多教程和案例,

欢迎搜索及关注:Crossin的编程教室

这里还有更多精彩。一起学,走得远!


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK