Search code examples
powerbipowerbi-desktopvega-litedeneb

Double donut/Multilayer Donut chart in Power BI


I need a double Donut chart in power BI. Custom visual in power bi or Deneb(vegalite) solution needed. I have data like this

Year Category value
2021 Category 1 25
2021 Category 2 50
2021 Category 3 25
2022 Category 1 50
2022 Category 2 25
2022 Category 3 25

Image the expected output in power bi I needed. Thanks in advance


Solution

  • Next time at least have a test in vega editor and let us know where you've had troubles. Here is an example that will get you started..

    In your example your donut sections did not start at "midnight". This is always good to do as it is much easier for the user to see how large the donut sections are just like reading the time (00:15, 00:30 etc).

    • Edit: Made year dynamic based on min and max year transforms.
    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "description": "A simple donut chart with embedded data.",
      "data": {
        "values": [
          {"year": 2022, "category": 1, "value": 10},
          {"year": 2022, "category": 2, "value": 6},
          {"year": 2022, "category": 3, "value": 10},
          {"year": 2023, "category": 1, "value": 8},
          {"year": 2023, "category": 2, "value": 20},
          {"year": 2023, "category": 3, "value": 10}
        ]
      },
      "transform": [
        {
          "window": [{"op": "sum", "field": "value", "as": "year_total"}],
          "frame": [null, null],
          "groupby": ["year"]
        },
        {
          "calculate": "datum.value / datum.year_total * 100",
          "as": "percent_of_year_total"
        },
        {
          "joinaggregate": [{"op": "min", "field": "category", "as": "Yeartext"}],
          "groupby": ["year"]
        },
        {
          "joinaggregate": [{"op": "min", "field": "year", "as": "minYear"}],
          "groupby": []
        },
        {
          "joinaggregate": [{"op": "max", "field": "year", "as": "maxYear"}],
          "groupby": []
        }
      ],
      "encoding": {
        "tooltip": [
          {"field": "year", "title": "Year"},
          {"field": "value", "title": "Value"},
          {"field": "percent_of_year_total", "title": "Value %", "format": ".2f"}
        ],
        "theta": {"field": "percent_of_year_total", "type": "quantitative"},
        "color": {
          "field": "category",
          "type": "nominal",
          "scale": {"range": "category"}
        }
      },
      "layer": [
        {
          "transform": [{"filter": "datum.year == datum.maxYear"}],
          "mark": {"type": "arc", "innerRadius": 80, "radius": 100}
        },
        {
          "transform": [
            {"filter": "datum.year == datum.maxYear"},
            {"filter": "datum.category == datum.Yeartext"}
          ],
          "mark": {"type": "text", "color": "white"},
          "encoding": {
            "color": {"value": "black"},
            "text": {"field": "year"},
            "x": {"value": 100},
            "y": {"value": -10}
          }
        },
        {
          "transform": [{"filter": "datum.year == datum.minYear"}],
          "mark": {"type": "arc", "innerRadius": 59, "radius": 79}
        },
        {
          "transform": [
            {"filter": "datum.year == datum.minYear"},
            {"filter": "datum.category == datum.Yeartext"}
          ],
          "mark": {"type": "text", "color": "white"},
          "encoding": {
            "tooltip": null,
            "color": {"value": "black"},
            "text": {"field": "year"},
            "x": {"value": 100},
            "y": {"value": 55}
          }
        }
      ],
      "config": {"view": {"stroke": "transparent"}}
    }
    

    enter image description here