将选择捕捉到 week/month/year

snap selection to week/month/year

我在带有外部数据源的 crossfiltery 应用程序中使用 Vega Lite。

我希望图表上的选择具有时间尺度 "snap" 或 "round" 到我将在规范中提供的时间间隔。

我在 selections documentation 中没有看到任何关于此的信息,所以我想我可能需要从 Vega Lite 规范生成 Vega 规范,然后对其进行修补。这不是我做过的事情,但我很想学习。

但是我很惊讶没有在 SO、GitHub 或 Slack 上找到这个问题。我想我已经搜索了 {vega, vega-lite} x {round, snap} 的所有组合。

我能找到的最接近的是 an issue related to snapping selections for ordinal scales

我使用的术语有误吗?

事实证明,关于对齐序号尺度的问题更多是关于对齐时间间隔,this comment by Jeff Heer 涵盖了该主题。

生成的 Vega 表达式很长,但过程很简单:

  1. Get the x-coordinate value.
  2. Run it through a scale inversion (x.invert) to map from pixel domain to data domain.
  3. Perform "snapping" by rounding / truncating values in the data domain.
  4. Re-apply the x scale to get the snapped pixel coordinate.

我们可以更改 signalsupdate 字段来实现此截断。

对齐年份

假设所选内容名为 selection1。 Vega-Lite 将生成包含信号 selection1_x(为简洁起见已编辑)的 Vega 规范:

{
  "name": "selection1_x",
  "value": [],
  "on": [
    {
      "events": {
        "source": "scope",
        "type": "mousedown",
        "filter": // ... 
      },
      "update": "[x(unit), x(unit)]"
    },
    {
      "events": {
        "source": "scope",
        "type": "mousemove",
        "between": // ...
      },
      "update": "[selection1_x[0], clamp(x(unit), 0, width)]"
    },
    // ...

我们可以替换第一个 on 项中的 x(unit) 表达式和第二个 on 项中的 clamp(x(unit), 0, width) 表达式,使用上述步骤:

{
  "name": "selection1_x",
  "value": [],
  "on": [
    {
      "events": {
        "source": "scope",
        "type": "mousedown",
        "filter": // ...
      },
      "update": "[scale(\"x\",datetime(year(invert(\"x\",x(unit))),0)),scale(\"x\",datetime(year(invert(\"x\",x(unit))),0))]"
    },
    {
      "events": {
        "source": "scope",
        "type": "mousemove",
        "between": // ...
      },
      "update": "[selection1_x[0],scale(\"x\",datetime(year(invert(\"x\",clamp(x(unit),0,width))),0))]"
    },
    // ...

队伍越来越长,这还没有考虑小于一年的间隔。你可能不想手写这些东西!

更小的间隔

此方法支持截断到 Vega 的任何参数 datetime expression:

datetime(year, month[, day, hour, min, sec, millisec]) Returns a new Date instance. The month is 0-based, such that 1 represents February.

您必须至少指定年份和月份,因此上面的月份为零。

要对齐周,您可以从月份的日期中减去星期几:

[selection1_x[0], scale("x", datetime(
    year(invert("x", clamp(x(unit),0,width))),
    month(invert("x", clamp(x(unit),0,width))),
    date(invert("x", clamp(x(unit),0,width)))
        - day(invert("x", clamp(x(unit),0,width)))))]

我对 Vega 的了解还不够深入,不知道是否可以简化这些表达式。

前进

而且 vega-time 是 in the pipeline, providing the functionality of d3-time intervals,所以在不久的将来这应该会变得更简单!