上一篇文章中我们介绍了柱状图的创建和配置,在第一篇文章中也附上了有关于折线图的代码示例。那么当你接到一个需求,要把两组量纲不一样的数据放到一起的时候,折线图、柱状图,你选哪一个呢?
小学生才做选择,分析师我们都要!而且是一起要!
今天我们就来看一下pyecharts中折线图和柱状图怎样组合到一起。
首先,我们知道折线图和柱状图都是直接坐标系下的图表,都是由x轴和y轴组成,图表中可以添加多个数据项,但是数据中难免会遇到量纲不一致的数据,即便是量纲一样,有时候也会因为分组间的数据量级差异过大,导致数据量小的在图中完全看不清楚。这种情况大家应该很容易就会想到excel的副坐标轴了,那么pyecharts中如何实现副坐标轴呢?
在pyecharts的直角坐标系下,我们可以为x轴和y轴添加索引,这个索引的意思其实就是分配每条坐标轴一个id,在插入数据项的时候指定所属的坐标轴索引,就可以把数据项和坐标轴绑定到一起了。可是在大家的直观印象里,直角坐标系不就只有两条轴吗?那坐标轴索引有啥意义呢?
没错,直角坐标系里是只有两条坐标轴,但是这两条轴只是广义上的,指代的只是坐标轴方向而已,一个水平一个垂直。我们可以在这两个方向上去扩展自定义新的坐标轴,也就是对应excel中常用的副坐标轴。
pyecharts扩展坐标轴的操作很简单,以柱状图扩展坐标轴为例,就一个extand_axis函数,此函数中有三个可选参数,如果是要扩展y轴,那么只需要在参数yaxis中设置y轴相关配置项就可以了,当你需要额外增加x轴的时候,除了xaxis参数外还需要在xaxis_data中添加扩展x轴的数据。
但是只有这一步操作只能够在柱状图的基础上添加一个副坐标轴而已,单纯的在柱状图上增加一个副坐标轴也并没有多少实际意义,因为柱状图本身是为了更直观的比较每个柱子的高度,而采用两个量纲不一致的y轴并不能直接比较,而且很容易混淆不同数据系列,反倒是降低了柱状图的可读性。在实际工作当中,我们更多时候遇到的是这样的数据:
这个时候很明显不适合把销售额的绝对值和利润的百分比数据都使用柱状图来表示,通常我们是用柱状图表示绝对值、折线图表示百分比,并且使用相同的横坐标轴,就像这样:
pyecharts中是分别创建好柱状图和折线图,并为两者指定不同的y轴和相同的x轴,然后使用overlap函数将两者图层叠加到一起:
- from pyecharts import options, charts
- from pyecharts.commons.utils import JsCode
- month = ['{}月'.format(x) for x in list(range(1, 13))]
- amountA = [89, 90, 98, 107, 85, 81, 70, 89, 88, 96, 81, 64]
- amountB = [92, 85, 74, 120, 56, 70, 58, 92, 65, 51, 89, 76]
- rateA = ['24%', '22%', '21%', '19%', '24%', '18%', '21%', '16%', '22%', '22%', '17%', '15%']
- rateB = ['19%', '19%', '24%', '23%', '19%', '17%', '15%', '20%', '23%', '22%', '18%', '23%']
- bar = (
- charts.Bar(init_opts=options.InitOpts(width='1000px', height='400px')).
- set_global_opts(yaxis_opts=options.AxisOpts(name='销售额', position='left', max_=150)).
- add_xaxis(month).
- add_yaxis(series_name='A商品', y_axis=amountA, yaxis_index=0, color='#FFA54F', bar_width=20,
- itemstyle_opts=options.ItemStyleOpts(border_color='#BEBEBE', border_width=2, border_type='dotted')).
- add_yaxis(series_name='B商品', y_axis=amountB, yaxis_index=0, color='#FF4500', bar_width=20,
- itemstyle_opts=options.ItemStyleOpts(border_color='#BEBEBE', border_width=2, border_type='dotted')).
- extend_axis(yaxis=options.AxisOpts(name='利润率', position='right', type_='value',
- axislabel_opts=options.LabelOpts(formatter='{value}%')))
- )
- line = (
- charts.Line(init_opts=options.InitOpts(width='1000px', height='400px')).
- add_xaxis(month).
- add_yaxis(series_name='A商品', y_axis=[int(x.replace('%', '')) for x in rateA], yaxis_index=1,
- label_opts=options.LabelOpts(is_show=True,
- formatter=JsCode("function (params) {return params.value[1] + '%'}"))).
- add_yaxis(series_name='B商品', y_axis=[int(x.replace('%', '')) for x in rateB], yaxis_index=1,
- label_opts=options.LabelOpts(is_show=True,
- formatter=JsCode("function (params) {return params.value[1] + '%'}")))
- )
- bar.overlap(line)
- bar.render('bar.html')
如上述代码所示,我们首先是创建了一个bar对象,然后对这个柱状图添加x轴y轴的数据项和相关配置,注意在这里我们指定了yaxis_index=0,明确了柱状图使用索引为0的y轴。接下来就是调用extend_axis函数,对bar扩展一个y轴,在扩展时我们不需要为y轴添加数据或是指定索引,因为这一步只是为了给接下来把折线图融合进来预留一个位置而已。注意到在第19行设置轴标签的代码中有formatter这一参数,在坐标轴配置中指的是坐标轴刻度的单位,“{value}”就是原本的整型刻度,我们在后面加上一个“%”就变成了百分数。
继续创建折线图line,为line输入x、y轴数据,这里需要注意的是我们y轴是百分比数据,对于echarts来说不可读,所以我们要把他后面的“%”去掉并转换成整型数字,然后在label_opts参数中设置数据项标签的显示格式,注意这里的formatter和上一个设置y轴标签的formatter传入的值并不一样,我们把它区分开来讲:
(1)轴标签设置中,可以直接使用“{value}%”的形式来格式化标签,“{value}”指的就是轴标签刻度值,后接需要格式化输出的字符串就可以了
(2)在设置柱状图的数据标签时,可以通过“{c}%”来将数值格式化为百分数,或是将百分号改为其他表示单位的符号,同样的还可以用“{a}”、“{b}”分别指代系列名称(A商品或B商品)、类目值(1月、2月等)。
(3)折线图原本与柱状图完全一致的,但由于pyecharts开发者将折线图的数据系列写成了由类目和数值组成的而为数组,使得echarts对“{c}”识别出错,导致无法只针对数值项格式化,故而此处暂由JsCode代替。希望开发者们可以早日修复这一问题,大家也可以关注我们的文章,后续会将手动修改pyecharts的源文件的方法整理出来,供大家参考。
(4)散点图(气泡)图 : {a}(系列名称),{b}(数据名称),{c}(数值数组)
(5)地图 : {a}(系列名称),{b}(区域名称),{c}(合并数值)
(6)饼图、仪表盘、漏斗图: {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
在柱状图、折线图都设置完毕后,我们就可以overlap将两者图层叠加起来了。这里需要注意的就是overlap的两者前后关系了,规则是:在谁的基础上扩展了坐标轴,就使用谁来调用overlap,图层叠加后仍然使用它来render生成html文件。