Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

July 7 - July 17 | Round 2 of the Power BI Dataviz World Championships. Don't miss your chance! Learn more

Reply
patBear
Helper I
Helper I

Deneb - 3x3 subplot

I'm wanting to create a chart (I'm calling it a 3x3 subplot, but this may not be the correct name) in Deneb: for each categorical x and y value, I want a stacked bar chart of the project names. [Eventually, colors will be added from a z value, highlighting based on group or tier, etc.] I'm using this sample data

ZPBh7.png

and the code below. Currently, the bars are layered rather than stacked. I think I need to incorporate this transformation (measure cnt = COUNT('Table'[name]))

  "transform": [
    {
      "stack": "cnt",
      "as": ["ymin", "ymax"],
      "groupby": ["x", "y"]
    }
  ]

but I'm not sure how/where to insert it into the code below.

{
  "data": {"name": "dataset"},
  "layer": [
    {
      "mark": {
        "type": "bar",
        "stroke": "black",
        "strokeWidth": 1,
        "tooltip": true
      }
    },
    {
      "mark": "text",
      "encoding": {
        "text": {
          "field": "Name",
          "type": "nominal"
        }
      }
    }
  ],
  "encoding": {
    "x": {
      "field": "x",
      "type": "nominal",
      "scale": {
        "domain": ["low", "med", "high"]
      },
      "axis": {
        "title": "X Level",
        "labelAngle": 0
      }
    },
    "y": {
      "field": "y",
      "type": "nominal",
      "scale": {
        "domain": ["high", "med", "low"]
      },
      "axis": {"title": "Y Level"}
    }
  }
}

 To be clear, I'm aiming for this sort of chart where names have been removed. 

5DFV0.png
 
1 ACCEPTED SOLUTION
dm-p
Super User
Super User

Hi @patBear,

This should be achievable with a stack transform at the top-level, as you have guessed. To make the stack work better, I've added a window / row_number transform beforehand to group and sort each square by z:

 

  "transform": [
    {
      "window": [
        {
          "op": "row_number",
          "as": "group_row_number"
        }
      ],
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}]
    },
    {
      "stack": "group_row_number",
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}],
      "as": ["y1", "y2"]
    }
  ]

 

This has the effect of assigning a sequence to each row as follows:

Name group_row_number
AA 2
BB 1
CC 1
DD 1
EE 2
FF 1
GG 2
HH 1

We then use the same group approach in the stack, and use the group_row_number as the field to stack on.

Once this is done, I just need to use a yOffset in the encoding with the generated y1 field:

 

    "yOffset": {
      "field": "y1",
      "scale": {"reverse": true}
    }

 

One thing I've done is reverse the scale so that marks are drawn from the bottom of each square.

The resulting visual looks as follows:

dmp_0-1656547796119.png

For completeness, here's the full spec:

 

{
  "data": {"name": "dataset"},
  "transform": [
    {
      "window": [
        {
          "op": "row_number",
          "as": "group_row_number"
        }
      ],
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}]
    },
    {
      "stack": "group_row_number",
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}],
      "as": ["y1", "y2"]
    }
  ],
  "layer": [
    {
      "mark": {
        "type": "bar",
        "stroke": "black",
        "strokeWidth": 1,
        "tooltip": true
      }
    },
    {
      "mark": "text",
      "encoding": {
        "text": {
          "field": "Name",
          "type": "nominal"
        }
      }
    }
  ],
  "encoding": {
    "x": {
      "field": "x",
      "type": "nominal",
      "scale": {
        "domain": ["low", "med", "high"]
      },
      "axis": {
        "title": "X Level",
        "labelAngle": 0
      }
    },
    "y": {
      "field": "y",
      "type": "nominal",
      "scale": {
        "domain": ["high", "med", "low"]
      },
      "axis": {"title": "Y Level"}
    },
    "yOffset": {
      "field": "y1",
      "scale": {"reverse": true}
    }
  }
}

 

Hopefully this is what you're expecting, but should be possible to tweak to your liking if not.

Good luck (and thanks for considering Deneb)!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




View solution in original post

2 REPLIES 2
dm-p
Super User
Super User

Hi @patBear,

This should be achievable with a stack transform at the top-level, as you have guessed. To make the stack work better, I've added a window / row_number transform beforehand to group and sort each square by z:

 

  "transform": [
    {
      "window": [
        {
          "op": "row_number",
          "as": "group_row_number"
        }
      ],
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}]
    },
    {
      "stack": "group_row_number",
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}],
      "as": ["y1", "y2"]
    }
  ]

 

This has the effect of assigning a sequence to each row as follows:

Name group_row_number
AA 2
BB 1
CC 1
DD 1
EE 2
FF 1
GG 2
HH 1

We then use the same group approach in the stack, and use the group_row_number as the field to stack on.

Once this is done, I just need to use a yOffset in the encoding with the generated y1 field:

 

    "yOffset": {
      "field": "y1",
      "scale": {"reverse": true}
    }

 

One thing I've done is reverse the scale so that marks are drawn from the bottom of each square.

The resulting visual looks as follows:

dmp_0-1656547796119.png

For completeness, here's the full spec:

 

{
  "data": {"name": "dataset"},
  "transform": [
    {
      "window": [
        {
          "op": "row_number",
          "as": "group_row_number"
        }
      ],
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}]
    },
    {
      "stack": "group_row_number",
      "groupby": ["x", "y"],
      "sort": [{"field": "z"}],
      "as": ["y1", "y2"]
    }
  ],
  "layer": [
    {
      "mark": {
        "type": "bar",
        "stroke": "black",
        "strokeWidth": 1,
        "tooltip": true
      }
    },
    {
      "mark": "text",
      "encoding": {
        "text": {
          "field": "Name",
          "type": "nominal"
        }
      }
    }
  ],
  "encoding": {
    "x": {
      "field": "x",
      "type": "nominal",
      "scale": {
        "domain": ["low", "med", "high"]
      },
      "axis": {
        "title": "X Level",
        "labelAngle": 0
      }
    },
    "y": {
      "field": "y",
      "type": "nominal",
      "scale": {
        "domain": ["high", "med", "low"]
      },
      "axis": {"title": "Y Level"}
    },
    "yOffset": {
      "field": "y1",
      "scale": {"reverse": true}
    }
  }
}

 

Hopefully this is what you're expecting, but should be possible to tweak to your liking if not.

Good luck (and thanks for considering Deneb)!

Daniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!


On how to ask a technical question, if you really want an answer (courtesy of SQLBI)




Thanks for this.  It's exactly the structure I was needing to move forward!

Helpful resources

Announcements
FabCon and SQLCon Barcelona 2026

FabCon & SQLCon – Barcelona 2026

Join us in Barcelona for FabCon and SQLCon, the Fabric, Power BI, SQL, and AI community event. Save €200 with code FABCMTY200.

60 days of Data Days Carousel

Data Days 2026

Join Data Days 2026: 60 days of free live/on-demand sessions, challenges, study groups, and certification opportunities.

Power BI DataViz World Championships carousel

Power BI DataViz World Championships - June 2026

A new Power BI DataViz World Championship is coming this June! Don't miss out on submitting your entry.

Top Solution Authors