在Vega-Lite中创建关联时间的水平状态栏可行性问询
如何基于时间序列数据绘制状态时段矩形图?
我尝试用矩形标记对象在不同时段的「状态」区域,使用的时间序列数据格式如下:
[ { "time": "<time>", "value": 1 }, { "time": "<time>", "value": 1 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 1 }, { "time": "<time>", "value": 1 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 0 }, { "time": "<time>", "value": 2 }, { "time": "<time>", "value": 2 } ]
普通柱状图只能展示各状态的总时长,无法关联状态与具体时间区间。我想要实现的效果是:X轴为时间轴,Y轴对应不同状态值,每个状态以连续的彩色矩形块展示其持续的时间段,直观呈现状态随时间的变化。
以洗衣机为例:关机、开机、脱水、漂洗等状态对应数字0、1、2、3……,状态变化或定期轮询时,数值会被记录到时间序列数据库,希望在X轴为时间的图表中水平展示这些状态的持续时段。
我测试了以下Vega-Lite代码,但无法得到预期效果:
{ "$schema": "https://vega.github.io/schema/vega-lite/v2.json", "autosize": { "type": "fit", "contains": "padding" }, "data": { "values": [ {"state": 0, "time": "2019-10-01"}, {"state": 2, "time": "2019-10-02"}, {"state": 0, "time": "2019-10-03"}, {"state": 1, "time": "2019-10-04"}, {"state": 0, "time": "2019-10-05"}, {"state": 0, "time": "2019-10-06"}, {"state": 1, "time": "2019-10-07"} ] }, "mark": { "type": "bar" }, "config": { "axis": { "labels": true, "domain": true, "ticks": false, "grid": false }, "view": { "fill": "transparent", "stroke": "transparent" }, "scale": { "bandPaddingInner": 0 } }, "encoding": { "x": { "field": "time", "type": "ordinal", "axis": true }, "y": { "field": "state", "type": "ordinal", "scale": { "domain": [] }, "axis": true }, "color": { "field": "state", "type": "ordinal", "legend": true, "scale": { "domain": [0,1,2], "range": ["#BD0000","#8DB319","#29ABE2"] } } } }
运行后得到的是每个时间点对应一个独立小柱子,无法展示状态的连续时段。请问该需求是否可行?怎么实现?
解决方案
这个需求完全可行,核心是先将离散的时间点数据转换为状态时段数据,再用Vega-Lite的rect标记绘制连续矩形。
1. 数据格式转换
将连续相同状态的时间点合并,记录每个状态的start(开始时间)、end(结束时间)和对应的state值。转换后的数据格式示例:
[ {"state": 0, "start": "2019-10-01", "end": "2019-10-01"}, {"state": 2, "start": "2019-10-02", "end": "2019-10-02"}, {"state": 0, "start": "2019-10-03", "end": "2019-10-06"}, {"state": 1, "start": "2019-10-07", "end": "2019-10-07"} ]
如果是动态数据,可以通过Python、JavaScript等代码自动合并连续相同状态的记录。
2. 修改后的Vega-Lite代码
使用rect标记定义时间区间,实现连续状态块的展示:
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "autosize": { "type": "fit", "contains": "padding" }, "data": { "values": [ {"state": 0, "start": "2019-10-01", "end": "2019-10-01"}, {"state": 2, "start": "2019-10-02", "end": "2019-10-02"}, {"state": 0, "start": "2019-10-03", "end": "2019-10-06"}, {"state": 1, "start": "2019-10-07", "end": "2019-10-07"} ] }, "mark": "rect", "encoding": { "x": { "field": "start", "type": "temporal", "axis": {"title": "时间"} }, "x2": {"field": "end"}, "y": { "field": "state", "type": "ordinal", "axis": {"title": "状态"} }, "color": { "field": "state", "type": "ordinal", "legend": {"title": "状态"}, "scale": { "domain": [0,1,2], "range": ["#BD0000","#8DB319","#29ABE2"] } } }, "config": { "axis": { "domain": true, "ticks": true }, "view": { "fill": "transparent" } } }
关键说明
- 用
rect标记替代bar,通过x和x2定义每个状态的时间区间 - 将时间字段设置为
temporal(时间类型),确保X轴按时间顺序排列 - 合并连续相同状态的记录,避免出现碎片化的小矩形
内容的提问来源于stack exchange,提问作者Gene Parmesan
相关产品推荐
相关产品推荐

