Search code examples
vega-lite

Vega-lite: Why does graph width affect how the axis labels are formatted?


When rendering a graph where the X-axis is based on a timestamp which is represented as seconds since the Unix Epoch, I'm observing weird behavior in the generated labels for specific graph widths. I've experimented with the vega-lite online editor with a stripped down version of my dataset and only essential configuration options. When width is specified between 521-594, then the timestamp labels render as just time (repeating 6AM, 6PM) for a span of days:

Chart with only time

These labels are unacceptably vague. At other widths, the generated labels are what I expect:

Chart with day and time

See this vega-lite editor and modify the width to see how going outside the range of 521-594 affects the labels on the X-axis.

One thing about use of "scale": {"type": "utc"} in this configuration: removing this does resolve the labeling issue, but then the time shown is not what I want. It is displayed in local time rather than UTC.

I've come up with some workarounds: change the width of the graph or specify a static label format. The latter introduces it's own problems depending on the specified format, since the same label can be used, confusingly, multiple times, e.g. Mon Mar 23, Mon Mar 23 for different times of that day.

I attempted to find different ways to "fix" the labels via conditional formatting. However, based on examples in the documentation, expressions for creating a format seem limited to static conditions like "is this the first month of the year?" and not relational ones like, "is the day for this label the same as the previous label?" If it's possible to generate more dynamic axis labels via formatting, I'm open to that advice. However, vega-lite generally does a good job of generating the labels without further configuration, so understanding why that isn't working for this type of data at specific widths is more what I'm after.

So, is my configuration missing something? Do I have any other options other than the workarounds I've mentioned?


Solution

  • The label positions and formats are determined automatically based on the content of the chart and the space available (so that labels do not overlap). If the automatic results are not what you want, you can more closely control the tick positions and labels using appropriate axis label and tick properties.

    For example, here we use d3 time formats to precisely specify the format of the date labels:

      "encoding": {
        "x": {
          "field": "timestamp",
          "type": "temporal",
          "scale": {"type": "utc"},
          "axis": {"format": "%b %e, %I%p"}
        },
        "y": {"field": "amount", "type": "quantitative"}
      }
    

    enter image description here

    Full chart spec in the editor