为Plotly.js作图增加ggplot2风格
前言
之前用Python做数据可视化的时候经常用Plotly,感觉效果还不错,尤其是类似R语言里ggplot2
包的风格,看上去比较专业。前不久使用Plotly.js,却发现居然没有这个风格,想想这不科学啊,所以干脆把这个风格的配置提取了出来,用在了JS上面。
Plotly Python风格设置
Plotly模板对象
Python的Plotly库支持设置主题风格,有内置的主题,并且支持自定义主题。具体的说明参见:Theming and templates in Python。
1 | import plotly.io as pio |
通过上面的代码查看内置的模板(在Jupyter Lab中),可以发现自带的有ggplot2
模板。由技术文档可知,模板是plotly.graph_objs.layout._template.Template
类,其中由两个关键的属性:
layout
,布局属性,是一个图形(对象,其结构与图形的布局属性完全相同。当为模板布局的属性提供值时,这些值将用作应用此模板的任何图中的默认值;data
,数据属性用于自定义添加到应用模板的图窗的迹线(traces)属性的默认值。此数据属性包含一个类型为go.layout.template.Data
的图形对象,该对象具有以每种支持的trace类型命名的属性,然后为这些类型属性分配相应类型的图形对象跟踪的列表或元组。也就是不同类型的图表(例如scatter、bar、histogram)的风格是分别定义的。
此外,还可以看到一个关键的方法——to_plotly_json
,可以将Template对象导出为JSON对象,这个东西,很有可能与我们为Plotly.js设置风格有关。
模板对象调用分析
Plotly Python最后的渲染是是通过Plotly.js实现的,那么这个过程中,模板对象是怎么使用的呢?看一下源码一探究竟。
根据Plotly能够导出HTML, 看了一下plotly.io
模块,其中的to_html()
能够将Figure
对象转换为html代码:
其中关键的代码部分如下:
1 | # Serialize config dict to JSON |
上面代码中的Plotly.newPlot()
正是Plotly.js用于画图的函数。进一步分析发现,jlayout
参数中有template
字段。
那么,template
就是这么起作用的吗?
进一步查看plotly\express\_core.py
中的代码,可以发现:
apply_default_cascade()
将传入的template
参数转换为Template
对象,并对颜色、符号进行设置;configure_cartesian_marginal_axes()
会对template
缺少的一些参数设置默认值;make_figure()
通过update_layout()
将template
实例赋给Figure
对象。
这样,等到作图的时候,所有template
的设置就传递给Plotly.newPlot()
了,而对于不是plotly.express
的作图,也就是普通作图的时候,都是通过update_layout()
来实现的。
因此,我们所要做的就是,把Plotly Python中的template JSON作为Plotly.js作图layout参数的template
字段传递进去。
Plotly.js添加模板
以ggplot2模板为例。
首先,我们使用to_plotly_json()
将pio.templates['ggplot2']
导出为JSON。
根据Ploltly.js官方的说明文档——JavaScript Figure Reference: layout
,将导出的JSON对象layout
参数的template
属性即可。
以下是测试效果:
See the Pen Plotly.js with template by ZodiacWind (@zodiacwind) on CodePen.
小结
基于对Plotly Python和Plotly.js的使用经验,为Plotly.js提供了ggplot2的模板,当然其他自带的模板也可以用类似的方法添加。此外,我还尝试使用Typescript,虽然Plotly.js官方也提供了类型定义,但是发现可能因为版本更新的缘故,template的类型定义有一个小bug。总而言之,我觉得Plotly还是不错的,值得作为Echarts等流行可视化库之外的一个选择。