水球图(Liquid Fill Chart),听名字或许比较陌生,但从命名的角度也可以猜测出此类图像以球形水波显示。水球图属于填充仪表盘类,可以用于生动地展示单个百分比数据或评分数据。
Q : 那如果要展现定性变量的数值对比该怎么办呢?
如果将两类差别较大的数据利用颜色区分,是可以在一个水球中绘制的,但始终牢记,数据可视化的目的以传递正确数据信息为首,美观其次。如果是三类及以上的定性,我们是建议绘制多个水球图,排布进行对比分析。
水球图示例如下:
假定我们现在的目标是对比城市的恩格尔系数(由于同栏目中收集了2020年城市统计公报,已经存在了符合条件的数据就顺便用了),城市仍然是随机挑选的八座:['北京','重庆','武汉','深圳','南京','广州','成都','上海']。
现在我们手上的数据是定性一维的对比,全绘制在一张图中显然不合适,因此我们考虑绘制八张水球图然后二行八列排布呈现,再进行对比分析。
excel数据展示如下:
接下来导入数据:
import pandas as pd
inout_data = pd.DataFrame(pd.read_excel('./居民人均可支配.xlsx'))
rate_data = {}
for i in range(8):
rate_data[inout_data['城市'][i]] = inout_data['恩格尔系数'][i]
用于绘图的数据结构如下所示:
这里我们是使用的python语言,借助pyecharts包实现绘制。
from pyecharts import options as opts
from pyecharts.charts import Liquid
from pyecharts.globals import SymbolType
city8_fullname = ['北京','重庆','武汉','深圳','南京','广州','成都','上海']
colors = ['#ff967c','#f1da7a','#a4be5c','#75bbfd',
'#658cbb','#ce5dae','#fc824a','#4b57db']
for i in range(8):
city = city8_fullname[i]
col = [colors[i]]
d = round(rate_data[city],2)
print(city,"完成!")
c = (
Liquid()
.add("",[d], is_outline_show=False,color =[col])
.set_global_opts(title_opts=opts.TitleOpts(title=city,pos_left="center"))
.render("./绘图结果/"+city+"-恩格尔系数-水球图.html")
)
得到的结果整理拼接即为:
其实我们也可以发现,这类图形在数据差异小的情况下进行对比缺乏优势,因为水波在展示的时候是会上下起伏变动的,影响视觉判断。因此,我们在进行展示和说明的过程中,还是依据中间显示的数值说话。
接下来,我们对代码中的部分参数和结果进行说明:
①:round是为了取最后在图上显示XX%格式才增加的吗?
不是,无论小数延后到千分还是万分位,默认设置下的水球图在数据呈现上只会显示百分位。比如我们的数值输入0.0007,画出来的数值标注为0%。因此我们还是不断强调要反映真实性,尽量选择差异较大的数据来画水球图。
如果我们要调整精度,需要借助导入的JSCode对label_opts进行修改,举例如下:
from pyecharts import options as opts
from pyecharts.charts import Liquid
from pyecharts.globals import SymbolType
from pyecharts.commons.utils import JsCode
c = (
Liquid()
.add("",[0.23141], is_outline_show=False,color =['#75bbfd'],
label_opts=opts.LabelOpts(
font_size=40,#默认50
formatter=JsCode(
"""function (param) {
return (Math.floor(param.value * 100000) / 1000) + '%';
}"""
),
position="inside"))
.set_global_opts(title_opts=opts.TitleOpts(title="示例",pos_left="center"))
.render("./绘图结果/水球图示例2.html")
)
在JavaScript里面的return,我们这里用的是floor,取不大于数值的最大整数;如果是要显示两位小数,则乘10000再除100,如果是一位小数则乘1000再除10,以此类推。
②:is_outline_show 是否展现外围的环线。
因为外围环线统一配色是深蓝,对案例中多色区分的呈现会有负作用,因此我上面选的是false。如果改成True,以北京为例:
③:.add中第一个双引号是什么?
在是否增加环线部分,我们同时变更了add行(.add("加油加油“,[d]...) 。这里加的文本,是对数据的说明,用于数据交互呈现时的辅助说明,不是我们的title。
④:为什么要对数值和颜色列表化?
对于每个水球的绘制,我们输入的都是列表数据。这里需要注意的是,如果我们需要在一张图中绘制两个水波,比如某次选班长活动中,A同学是获得了52%的同学支持,B同学只有30%,我们希望绘制一幅水球图体现两者的差距。
from pyecharts import options as opts
from pyecharts.charts import Liquid
from pyecharts.globals import SymbolType
c = (
Liquid()
.add(["A","B"],[0.52,0.3], is_outline_show=True,color =['#fc824a','#ce5dae'])
.set_global_opts(title_opts=opts.TitleOpts(title="示例",pos_left="center"))
.render("./绘图结果/水球图示例2.html")
)
此时,我们在数据的列表中放入了两个数值【由于水波是覆盖型绘制,必须是大的在前面,小的在后面,否则虽然会自动调整透明度保证能看到不同水波,但是在交互时无法显现小类的数值】,相应的,为了更好区分,color属性也对应配两个颜色。
但是,前面“A”,“B”变成list有用吗?它并不会如我们想的一般一一对应显示,结果如下:
而且我们可以发现有个弊端,只显示了第一个数值百分比。
⑤:能不能设置参数改变水球的球形?
当然可以。其实细心的朋友可以发现,我导入的symboltype还没派上用场。其实在add中有shape参数,默认值“circle”。
可以调整设置值和形状对应如下:
shape=SymbolType.RECT ------- 矩形
shape=SymbolType.DIAMOND ------ 钻石型
shape=SymbolType.ROUND_RECT ------ 圆角矩形
shape=SymbolType.TRIANGLE ------ 三角形
shape=SymbolType.ARROW ------ 箭头型
比如我们用箭头型举例一个单数值:
希望对您有所帮助~