如何将Vega-Lite的Brush吸附到日期以实现过滤?
问题描述
我有一个text mark和两个垂直拼接的area mark。每个area mark都配置了brush参数,area 2的brush用来控制area 1的定义域。我想用选中的brush区域过滤text mark,但x轴是时间型,brush生成的是毫秒级区间,我需要按天单位进行brush操作。将timeUnit改为yearmonthdate后,过滤完全失效。

如何让brush区间吸附到单个日期,同时保持原有的过滤功能?我已修改之前的代码,更改了timeUnit并过滤了单一年份,以便更易选中单个日期。
原代码如下:
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": {"url": "data/sp500.csv"}, "transform": [ { "filter": {"timeUnit": "year", "field": "date", "lte": "2000"} } ], "params": [ {"name": "a", "expr": "brush1.date?true:false"}, {"name": "b", "expr": "brush2.date?true:false"}, ], "vconcat": [ { "title": "text mark:", "width": 480, "mark": "text", "transform": [ {"extent": "date", "param": "c"}, { "joinaggregate": [ {"op": "min", "field": "date", "as": "min_date"}, {"op": "max", "field": "date", "as": "max_date"} ] }, { "calculate": "a?brush1.date[0]:b?brush2.date[0]:datum.min_date", "as": "min_date" }, { "calculate": "a?brush1.date[1]:b?brush2.date[1]:datum.max_date", "as": "max_date" }, { "filter": "datum.date >= datum.min_date & datum.date <= datum.max_date" } ], "encoding": { "text": { "value": { "expr": "timeFormat(a?brush1.date[0]:b?brush2.date[0]:c[0], '%d %b %Y') + ' to ' + timeFormat(a?brush1.date[1]:b?brush2.date[1]:c[1], '%d %b %Y')" } } } }, { "title": "area mark 1:", "width": 480, "mark": "area", "params": [ {"name": "brush1", "select": {"type": "interval", "encodings": ["x"]}} ], "encoding": { "x": { "field": "date", "type": "temporal", "timeUnit": "yearmonthdate", "scale": {"domain": {"param": "brush2"}}, "axis": {"title": ""} }, "y": {"field": "price", "type": "quantitative"} } }, { "title": "area mark 2:", "width": 480, "height": 60, "mark": "area", "params": [ {"name": "brush2", "select": {"type": "interval", "encodings": ["x"]}} ], "encoding": { "x": {"field": "date", "type": "temporal", "timeUnit": "yearmonthdate"}, "y": { "field": "price", "type": "quantitative", "axis": {"tickCount": 3, "grid": false} } } } ] }
解决方案
核心是统一时间字段的处理逻辑,让brush生成的区间和数据过滤使用相同的时间单位对齐,具体修改步骤如下:
让brush按日期单位吸附
在两个brush的select配置中添加timeUnit: 'yearmonthdate'和resolve: 'global',强制brush区间自动对齐到天级单位:// 以brush1为例,brush2做相同修改 { "name": "brush1", "select": { "type": "interval", "encodings": ["x"], "resolve": "global", "timeUnit": "yearmonthdate" } }修正过滤逻辑的时间比较
原代码中直接用原始毫秒级date和brush区间比较,导致不匹配。需要把两边的时间都转换为yearmonthdate单位后再比较,修改text mark的filter表达式:{ "filter": "timeUnit('yearmonthdate', datum.date) >= timeUnit('yearmonthdate', datum.min_date) && timeUnit('yearmonthdate', datum.date) <= timeUnit('yearmonthdate', datum.max_date)" }简化冗余参数
删掉原代码中params里的a、b参数,直接在计算表达式中判断brush是否存在区间,减少冗余:{ "calculate": "brush1.date ? brush1.date[0] : brush2.date ? brush2.date[0] : datum.min_date", "as": "min_date" }
完整修改后的代码
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": {"url": "data/sp500.csv"}, "transform": [ { "filter": {"timeUnit": "year", "field": "date", "lte": "2000"} } ], "vconcat": [ { "title": "text mark:", "width": 480, "mark": "text", "transform": [ {"extent": "date", "param": "c"}, { "joinaggregate": [ {"op": "min", "field": "date", "as": "min_date"}, {"op": "max", "field": "date", "as": "max_date"} ] }, { "calculate": "brush1.date ? brush1.date[0] : brush2.date ? brush2.date[0] : datum.min_date", "as": "min_date" }, { "calculate": "brush1.date ? brush1.date[1] : brush2.date ? brush2.date[1] : datum.max_date", "as": "max_date" }, { "filter": "timeUnit('yearmonthdate', datum.date) >= timeUnit('yearmonthdate', datum.min_date) && timeUnit('yearmonthdate', datum.date) <= timeUnit('yearmonthdate', datum.max_date)" } ], "encoding": { "text": { "value": { "expr": "timeFormat(brush1.date ? brush1.date[0] : brush2.date ? brush2.date[0] : c[0], '%d %b %Y') + ' to ' + timeFormat(brush1.date ? brush1.date[1] : brush2.date ? brush2.date[1] : c[1], '%d %b %Y')" } } } }, { "title": "area mark 1:", "width": 480, "mark": "area", "params": [ { "name": "brush1", "select": { "type": "interval", "encodings": ["x"], "resolve": "global", "timeUnit": "yearmonthdate" } } ], "encoding": { "x": { "field": "date", "type": "temporal", "timeUnit": "yearmonthdate", "scale": {"domain": {"param": "brush2"}}, "axis": {"title": ""} }, "y": {"field": "price", "type": "quantitative"} } }, { "title": "area mark 2:", "width": 480, "height": 60, "mark": "area", "params": [ { "name": "brush2", "select": { "type": "interval", "encodings": ["x"], "resolve": "global", "timeUnit": "yearmonthdate" } } ], "encoding": { "x": {"field": "date", "type": "temporal", "timeUnit": "yearmonthdate"}, "y": { "field": "price", "type": "quantitative", "axis": {"tickCount": 3, "grid": false} } } } ] }
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

