Search code examples
jsonchartsvisualizationvega-lite

Is it possible to left-align the row label in a Row Facet?


Is it possible to left-align the row label in a Row Facet?

In this case the row field of "Sub-Category".

For example, ...

Accessories

Appliances

Art

....................................................................................................................................................................................................

  {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-01-31T00:00:00",
        "Sales": 2126,
        "Profit": 476
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-02-29T00:00:00",
        "Sales": 2437,
        "Profit": 623
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-03-31T00:00:00",
        "Sales": 3952,
        "Profit": 1192
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-04-30T00:00:00",
        "Sales": 2142,
        "Profit": 358
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-05-31T00:00:00",
        "Sales": 3751,
        "Profit": 1190
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-06-30T00:00:00",
        "Sales": 4849,
        "Profit": 1028
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-07-31T00:00:00",
        "Sales": 7589,
        "Profit": 2403
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-08-31T00:00:00",
        "Sales": 4962,
        "Profit": 1154
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-09-30T00:00:00",
        "Sales": 9727,
        "Profit": 2778
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-10-31T00:00:00",
        "Sales": 5032,
        "Profit": 909
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-11-30T00:00:00",
        "Sales": 8390,
        "Profit": 2181
      },
      {
        "Sub-Category": "Accessories",
        "MonthendDate": "2020-12-31T00:00:00",
        "Sales": 4989,
        "Profit": 1380
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-01-31T00:00:00",
        "Sales": 2548,
        "Profit": 423
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-02-29T00:00:00",
        "Sales": 3521,
        "Profit": 977
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-03-31T00:00:00",
        "Sales": 2474,
        "Profit": 308
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-04-30T00:00:00",
        "Sales": 645,
        "Profit": -144
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-05-31T00:00:00",
        "Sales": 2578,
        "Profit": 692
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-06-30T00:00:00",
        "Sales": 3160,
        "Profit": 897
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-07-31T00:00:00",
        "Sales": 1211,
        "Profit": 197
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-08-31T00:00:00",
        "Sales": 7105,
        "Profit": 1621
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-09-30T00:00:00",
        "Sales": 3088,
        "Profit": 427
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-10-31T00:00:00",
        "Sales": 3336,
        "Profit": 755
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-11-30T00:00:00",
        "Sales": 6746,
        "Profit": 1021
      },
      {
        "Sub-Category": "Appliances",
        "MonthendDate": "2020-12-31T00:00:00",
        "Sales": 6517,
        "Profit": 690
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-01-31T00:00:00",
        "Sales": 434,
        "Profit": 111
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-02-29T00:00:00",
        "Sales": 247,
        "Profit": 67
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-03-31T00:00:00",
        "Sales": 442,
        "Profit": 115
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-04-30T00:00:00",
        "Sales": 618,
        "Profit": 140
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-05-31T00:00:00",
        "Sales": 640,
        "Profit": 177
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-06-30T00:00:00",
        "Sales": 1019,
        "Profit": 262
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-07-31T00:00:00",
        "Sales": 867,
        "Profit": 251
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-08-31T00:00:00",
        "Sales": 733,
        "Profit": 199
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-09-30T00:00:00",
        "Sales": 971,
        "Profit": 267
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-10-31T00:00:00",
        "Sales": 642,
        "Profit": 123
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-11-30T00:00:00",
        "Sales": 1387,
        "Profit": 312
      },
      {
        "Sub-Category": "Art",
        "MonthendDate": "2020-12-31T00:00:00",
        "Sales": 862,
        "Profit": 199
      }   
    ]
  },
  "spacing": {"row": 2},
  "facet": {
    "row": {
      "field": "Sub-Category",
      "type": "nominal",
        "header": {
        "title": null,
        "labelAngle": 0,
        "labelPadding": 0,
        "titlePadding": -40,
        "labelAlign": "left"
      }
    }
  },
  "spec": {
    "width": 120,
    "height": 20,
    "view": {"stroke": "transparent"},
        "mark": {"type": "area", "interpolate": "natural"},
        "encoding": {
          "x": {
            "field": "MonthendDate",
            "type": "temporal",
            "title": null,
            "timeUnit": "yearmonth",
            "axis": {"format": "%b %y", "orient": "top",
            }
          },
          "y": {
            "field": "Sales",
            "type": "quantitative",
            "aggregate": "sum",
            "scale": {"zero": true},
            "axis": {"title": null, "labels": false, "ticks": false}
          }
        }
      },
  "resolve": {"scale": {"y": "shared"}}
}

Solution

  • I think this is currently a bug which you can read more about here: https://github.com/vega/vega-lite/issues/5547. If you edit the Vega spec instead, you can achieve what you want.

    Final Image

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "background": "white",
      "padding": 5,
      "data": [
        {
          "name": "source_0",
          "values": [
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-01-31T00:00:00",
              "Sales": 2126,
              "Profit": 476
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-02-29T00:00:00",
              "Sales": 2437,
              "Profit": 623
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-03-31T00:00:00",
              "Sales": 3952,
              "Profit": 1192
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-04-30T00:00:00",
              "Sales": 2142,
              "Profit": 358
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-05-31T00:00:00",
              "Sales": 3751,
              "Profit": 1190
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-06-30T00:00:00",
              "Sales": 4849,
              "Profit": 1028
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-07-31T00:00:00",
              "Sales": 7589,
              "Profit": 2403
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-08-31T00:00:00",
              "Sales": 4962,
              "Profit": 1154
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-09-30T00:00:00",
              "Sales": 9727,
              "Profit": 2778
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-10-31T00:00:00",
              "Sales": 5032,
              "Profit": 909
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-11-30T00:00:00",
              "Sales": 8390,
              "Profit": 2181
            },
            {
              "Sub-Category": "Accessories",
              "MonthendDate": "2020-12-31T00:00:00",
              "Sales": 4989,
              "Profit": 1380
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-01-31T00:00:00",
              "Sales": 2548,
              "Profit": 423
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-02-29T00:00:00",
              "Sales": 3521,
              "Profit": 977
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-03-31T00:00:00",
              "Sales": 2474,
              "Profit": 308
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-04-30T00:00:00",
              "Sales": 645,
              "Profit": -144
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-05-31T00:00:00",
              "Sales": 2578,
              "Profit": 692
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-06-30T00:00:00",
              "Sales": 3160,
              "Profit": 897
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-07-31T00:00:00",
              "Sales": 1211,
              "Profit": 197
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-08-31T00:00:00",
              "Sales": 7105,
              "Profit": 1621
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-09-30T00:00:00",
              "Sales": 3088,
              "Profit": 427
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-10-31T00:00:00",
              "Sales": 3336,
              "Profit": 755
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-11-30T00:00:00",
              "Sales": 6746,
              "Profit": 1021
            },
            {
              "Sub-Category": "Appliances",
              "MonthendDate": "2020-12-31T00:00:00",
              "Sales": 6517,
              "Profit": 690
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-01-31T00:00:00",
              "Sales": 434,
              "Profit": 111
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-02-29T00:00:00",
              "Sales": 247,
              "Profit": 67
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-03-31T00:00:00",
              "Sales": 442,
              "Profit": 115
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-04-30T00:00:00",
              "Sales": 618,
              "Profit": 140
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-05-31T00:00:00",
              "Sales": 640,
              "Profit": 177
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-06-30T00:00:00",
              "Sales": 1019,
              "Profit": 262
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-07-31T00:00:00",
              "Sales": 867,
              "Profit": 251
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-08-31T00:00:00",
              "Sales": 733,
              "Profit": 199
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-09-30T00:00:00",
              "Sales": 971,
              "Profit": 267
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-10-31T00:00:00",
              "Sales": 642,
              "Profit": 123
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-11-30T00:00:00",
              "Sales": 1387,
              "Profit": 312
            },
            {
              "Sub-Category": "Art",
              "MonthendDate": "2020-12-31T00:00:00",
              "Sales": 862,
              "Profit": 199
            }
          ]
        },
        {
          "name": "data_0",
          "source": "source_0",
          "transform": [
            {
              "type": "formula",
              "expr": "toDate(datum[\"MonthendDate\"])",
              "as": "MonthendDate"
            },
            {
              "field": "MonthendDate",
              "type": "timeunit",
              "units": ["year", "month"],
              "as": ["yearmonth_MonthendDate", "yearmonth_MonthendDate_end"]
            },
            {
              "type": "aggregate",
              "groupby": ["yearmonth_MonthendDate", "Sub-Category"],
              "ops": ["sum"],
              "fields": ["Sales"],
              "as": ["sum_Sales"]
            }
          ]
        },
        {
          "name": "row_domain",
          "source": "data_0",
          "transform": [{"type": "aggregate", "groupby": ["Sub-Category"]}]
        }
      ],
      "signals": [
        {"name": "child_width", "value": 120},
        {"name": "child_height", "value": 20}
      ],
      "layout": {
        "padding": {"row": 2, "column": 20},
        "columns": 1,
        "bounds": "full",
        "align": "all"
      },
      "marks": [
        {
          "name": "row_header",
          "type": "group",
          "role": "row-header",
          "from": {"data": "row_domain"},
          "sort": {"field": "datum[\"Sub-Category\"]", "order": "ascending"},
          "title": {
            "text": {
              "signal": "isValid(parent[\"Sub-Category\"]) ? parent[\"Sub-Category\"] : \"\"+parent[\"Sub-Category\"]"
            },
            "orient": "right",
            "style": "guide-label",
            "frame": "group",
            "baseline": "middle",
            "align": "right",
            "angle": 0,
            "offset": -60
          },
          "encode": {"update": {"height": {"signal": "child_height"}}},
          "axes": [
            {
              "scale": "y",
              "orient": "left",
              "grid": false,
              "labels": false,
              "ticks": false,
              "labelOverlap": true,
              "tickCount": {"signal": "ceil(child_height/40)"},
              "zindex": 0
            }
          ]
        },
        {
          "name": "column_header",
          "type": "group",
          "role": "column-header",
          "encode": {"update": {"width": {"signal": "child_width"}}},
          "axes": [
            {
              "scale": "x",
              "orient": "top",
              "grid": false,
              "format": "%b %y",
              "labelFlush": true,
              "labelOverlap": true,
              "tickCount": {"signal": "ceil(child_width/40)"},
              "zindex": 0
            }
          ]
        },
        {
          "name": "cell",
          "type": "group",
          "style": "cell",
          "from": {
            "facet": {
              "name": "facet",
              "data": "data_0",
              "groupby": ["Sub-Category"]
            }
          },
          "sort": {"field": ["datum[\"Sub-Category\"]"], "order": ["ascending"]},
          "encode": {
            "update": {
              "width": {"signal": "child_width"},
              "height": {"signal": "child_height"},
              "stroke": {"value": "transparent"}
            }
          },
          "marks": [
            {
              "name": "child_marks",
              "type": "area",
              "style": ["area"],
              "sort": {"field": "datum[\"yearmonth_MonthendDate\"]"},
              "from": {"data": "facet"},
              "encode": {
                "update": {
                  "interpolate": {"value": "natural"},
                  "orient": {"value": "vertical"},
                  "fill": {"value": "#4c78a8"},
                  "description": {
                    "signal": "\"MonthendDate (year-month): \" + (timeFormat(datum[\"yearmonth_MonthendDate\"], '%b %y')) + \"; Sum of Sales: \" + (format(datum[\"sum_Sales\"], \"\"))"
                  },
                  "x": {"scale": "x", "field": "yearmonth_MonthendDate"},
                  "y": {"scale": "y", "field": "sum_Sales"},
                  "y2": {"scale": "y", "value": 0},
                  "defined": {
                    "signal": "isValid(datum[\"yearmonth_MonthendDate\"]) && isFinite(+datum[\"yearmonth_MonthendDate\"]) && isValid(datum[\"sum_Sales\"]) && isFinite(+datum[\"sum_Sales\"])"
                  }
                }
              }
            }
          ],
          "axes": [
            {
              "scale": "x",
              "orient": "top",
              "gridScale": "y",
              "grid": true,
              "tickCount": {"signal": "ceil(child_width/40)"},
              "domain": false,
              "labels": false,
              "aria": false,
              "maxExtent": 0,
              "minExtent": 0,
              "ticks": false,
              "zindex": 0
            },
            {
              "scale": "y",
              "orient": "left",
              "gridScale": "x",
              "grid": true,
              "tickCount": {"signal": "ceil(child_height/40)"},
              "domain": false,
              "labels": false,
              "aria": false,
              "maxExtent": 0,
              "minExtent": 0,
              "ticks": false,
              "zindex": 0
            }
          ]
        }
      ],
      "scales": [
        {
          "name": "x",
          "type": "time",
          "domain": {"data": "data_0", "field": "yearmonth_MonthendDate"},
          "range": [0, {"signal": "child_width"}]
        },
        {
          "name": "y",
          "type": "linear",
          "domain": {"data": "data_0", "field": "sum_Sales"},
          "range": [{"signal": "child_height"}, 0],
          "zero": true,
          "nice": true
        }
      ],
      "config": {"style": {"cell": {"stroke": "transparent"}}}
    }