powerbivega-litedeneb

Multi-layer x-axis Date setup in Vega-Lite


I am trying to create a Vega-Lite visualization with a 4-layer x-axis. My goal is as follows:

  1. Year and Month should be displayed only on the first day of each month. I have already achieved this.
  2. Week numbers should be displayed only on the first day of each week, meaning there would be 4-5 week labels within a month. This is where I am stuck—I can't figure out a workaround.
  3. Day labels should appear for every single day on the x-axis.

This is my current code, which is partially working but not fully achieving the desired result:

{
  "data": {
    "values": [
      { "date": "2024-01-01", "value": 1, "group": 1 },
      { "date": "2024-03-01", "value": 6, "group": 1 },
      { "date": "2024-01-01", "value": 1, "group": 2 },
      { "date": "2024-03-01", "value": 6, "group": 2 },
      { "date": "2024-01-01", "value": 1, "group": 3 },
      { "date": "2024-02-01", "value": 3, "group": 3 },
      { "date": "2024-01-01", "value": 1, "group": 4 },
      { "date": "2024-03-01", "value": 5, "group": 4 },
      { "date": "2024-02-01", "value": 1, "group": 5 },
      { "date": "2024-03-01", "value": 6, "group": 5 },
      { "date": "2024-02-01", "value": 1, "group": 6 },
      { "date": "2024-03-01", "value": 6, "group": 6 },
      { "date": "2024-02-01", "value": 1, "group": 7 },
      { "date": "2024-04-01", "value": 3, "group": 7 },
      { "date": "2024-03-01", "value": 1, "group": 8 },
      { "date": "2024-05-01", "value": 5, "group": 8 }
    ]
  },
  "mark": "line",
  "encoding": {
    "x": {
      "field": "date",
      "type": "temporal",
      "axis": {
        "title": null,
        "orient": "top",
        "labelOverlap": "greedy",
        "labelFontWeight": "normal",
        "labelFontSize": 11,
        "tickCount": 15,
        "labelAlign": "left",
        "labelExpr": "[timeFormat(datum.value, '%m') == '01' && timeFormat(datum.value,'W%V') == 'W01' && timeFormat(datum.value,'%-d.%-m')=='1.1' ? timeFormat(datum.value, '%Y') : timeFormat(datum.value, '%Y'),timeFormat(datum.value, '%b'),timeFormat(datum.value,'W%V'),timeFormat(datum.value,'%-d.%-m')]",
        "labelOffset": 4,
        "labelPadding": 15,
        "tickSize": 30
      }
    },
    "y": {
      "field": "value",
      "type": "quantitative"
    }
  }
}

If anyone has suggestions or knows how to achieve this multi-layer x-axis with the desired functionality, I would greatly appreciate your help!

Thank you!


Solution

  • In such cases, vconcat can handle the job by separately formatting your axis with as many layers as you need. The only downside is that you have to manually adjust the height and width of your canvas.