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

Be one of the first to start using Fabric Databases. View on-demand sessions with database experts and the Microsoft product team to learn just how easy it is to get started. Watch now

Reply
sdrljaca
Frequent Visitor

Deneb: Packing instead of Overlapping Bubbles in Scatter Plot

Hi, I am learning Deneb and Vega-Ligt and I love it.

But bubbles are overlaping and I can not make bubbles Packing (as it is called in Charticulator). How?

Thank you!

15 REPLIES 15
Adamboer
Responsive Resident
Responsive Resident

To avoid overlapping bubbles in Deneb and Vega-Lite, you can use the "point" mark and set the "size" encoding to a fixed value or a calculated value based on your data. Additionally, you can set the "opacity" encoding to a lower value to make overlapping bubbles more transparent and distinguishable.

Here is an example of how to set up a basic bubble chart in Vega-Lite:

{
"mark": "point",
"encoding": {
"x": {"field": "x_value", "type": "quantitative"},
"y": {"field": "y_value", "type": "quantitative"},
"size": {"field": "size_value", "type": "quantitative"},
"opacity": {"value": 0.7}
}
}
You can adjust the "size" encoding to suit your needs, and you can also add other encodings like color or shape to further distinguish between bubbles.

avatorl
Impactful Individual
Impactful Individual

Hi @Adamboer  or should I call you ChatGPT?

 
Adamboer
Responsive Resident
Responsive Resident

That's your wish whatever you may call me, I don't have any issue in that.

avatorl
Impactful Individual
Impactful Individual

@KerKol thanks for tagging

@sdrljaca , do you means somethig like this?
avatorl_0-1677836812510.png
I can't help you with Vega-Lite solution (I never really worked with Vega-Lite), but it's easy to implement using Vega and "force" type of transformation.

See official Vega example: https://vega.github.io/vega/examples/packed-bubble-chart/

Also, my floral carttogram is a more advanced example of a packed bubble chart. See https://powerofbi.org/2023/02/18/floral-cartogram-how-do-we-govern-our-world/ for more details (and source code).

avatorl_2-1677836987474.png

Each flower has been placed inside of an invisible bubble with "force" transformation applied to make sure the bubbles (and the flowers) are not overlapping.

It's also possible to increase distance between bubbles or to allow partial overlapping.

If you'll decide to use Vega instead of Vega-Lite, feel free to contact me with any questions..

Hi, thank you as well.

In your "packed-bubble-chart" example it is only missing X and Y axis and tickBand that is "extent". We are really close.

BR, Srdjan

giammariam
Super User
Super User

@sdrljaca thanks for the additional info. I see that I mistakenly inserted the wrong link in my response above. This post explains how to do this. Essentially though you could use cloud storage such as google drive, onedrive, dropbox, or github, and then share the link here.



Madison Giammaria
Proud to be a Super User 😄
LinkedIn

Do you frequently use Deneb to provide insights to your stakeholders? Have you considered sponsoring this free and open source custom visual? More info here!

Hi, here is the Link 

Thank you for trying to help me,

Srđan

Hey @sdrljaca. So I've spent a ton of time on this because it is an interesting problem to try and solve. I've tried various approaches. Here's a couple notes.

  • The pack transform is only available in Vega, not Vega-Lite.
  • In Vega
    • I first faceted the dataset and set the row encoding to Site and the column encoding to Start-Up Year. I was able to recreate the original chart with this method, with the intent of applying the pack transform on each facet. I then performed data transforms to create the parent-child hierarchy necessary for the pack transform by fabricating a root node for each facet. This is where things started to break down. I couldn't figure out a way to perform the circle pack transform for each of these hierarchies, I could only perform it on a single dataset.
  • In Vega-Lite, I performed the same steps and looked into the steps involved in various circle packing algorithms with the crazy notion of trying to calculate the individual pack layouts through multiple transforms. Unfortunately, due to the recursive nature required for determining a given pack layout, vega/vega-lite transforms were just not set up for this.

I very well could be wrong, but ultimately it appears to me that the circle packing layout for each combination of Site and Start-Up Year would need to be computed outside of Vega/Vega-Lite using a circle packing algorithm. If you have access to query the source data via SQL, this could possibly be done with recursive CTEs. The resulting layout would then need to be loaded into Deneb as the source dataset.

 

Alternatively, this absolutely all could be done by building a Power BI Custom Visual using d3.js, but that would require quite a significant L.O.E. 

 

I'm not 100% convinced that this is impossible through faceting in Vega, but I was unable to figure it out. I'm going to tag some of the Deneb experts here to see if any of them have any thoughts.

Here are some files to get going if anybody out there has the bandwidth to look at this.

 

 



Madison Giammaria
Proud to be a Super User 😄
LinkedIn

Do you frequently use Deneb to provide insights to your stakeholders? Have you considered sponsoring this free and open source custom visual? More info here!
giammariam
Super User
Super User

Hey @sdrljaca, could you provide a sanitized .pbix (here's how)? I'd be happy to take a look.



Madison Giammaria
Proud to be a Super User 😄
LinkedIn

Do you frequently use Deneb to provide insights to your stakeholders? Have you considered sponsoring this free and open source custom visual? More info here!

Hi, yes of course, but how?
It says "The file type (.pbix) is not supported", that is why I am uploading print screen.

I want these bubbles not to be on top of each other, but to be distrubuted  within belonging quadrat (same I achieved in Charticulator with "Packing" distribution).Bubbles are overlapped.jpgand this would be some dummy data Bubbles are overlapped Data2.jpg

I might have a template for that... let me dig it up





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

Proud to be a Super User!




also tagging @avatorl 





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

Proud to be a Super User!




Something like this?

Deneb-Showcase/S&P Beeswarm Chart at main · PBI-David/Deneb-Showcase · GitHub

or this?

{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"usermeta": {
"deneb": {
"build": "1.4.0.0",
"metaVersion": 1,
"provider": "vega",
"providerVersion": "5.22.1"
},
"interactivity": {
"tooltip": true,
"contextMenu": true,
"selection": false,
"highlight": true,
"dataPointLimit": 50
},
"information": {
"name": "Kerry Kolosko Bubble Swarm",
"description": "[No Description Provided]",
"author": "Kerry Kolosko",
"uuid": "e363f508-0281-4f62-a1a3-115169706015",
"generated": "2023-03-03T08:30:42.639Z"
},
"dataset": [
{
"key": "__0__",
"name": "X",
"description": "",
"type": "numeric",
"kind": "column"
},
{
"key": "__1__",
"name": "ColourCategory",
"description": "",
"type": "text",
"kind": "column"
},
{
"key": "__2__",
"name": "Labels",
"description": "",
"type": "text",
"kind": "column"
},
{
"key": "__3__",
"name": "Y",
"description": "",
"type": "numeric",
"kind": "measure"
},
{
"key": "__4__",
"name": "BubbleSize",
"description": "",
"type": "numeric",
"kind": "measure"
}
]
},
"config": {
"autosize": {
"contains": "padding",
"type": "fit"
},
"view": {"stroke": "transparent"},
"font": "Segoe UI",
"arc": {},
"area": {
"line": true,
"opacity": 0.6
},
"bar": {},
"line": {
"strokeWidth": 3,
"strokeCap": "round",
"strokeJoin": "round"
},
"path": {},
"point": {
"filled": true,
"size": 75
},
"rect": {},
"shape": {},
"symbol": {
"strokeWidth": 1.5,
"size": 50
},
"text": {
"font": "Segoe UI",
"fontSize": 12,
"fill": "#605E5C"
},
"axis": {
"ticks": false,
"grid": false,
"domain": false,
"labelColor": "transparent",
"labelFontSize": 12,
"titleFont": "wf_standard-font, helvetica, arial, sans-serif",
"titleColor": "#252423",
"titleFontSize": 16,
"titleFontWeight": "normal"
},
"axisQuantitative": {
"tickCount": 3,
"grid": true,
"gridColor": "#C8C6C4",
"gridDash": [1, 5],
"labelFlush": false
},
"axisX": {"labelPadding": 5},
"axisY": {"labelPadding": 10},
"header": {
"titleFont": "wf_standard-font, helvetica, arial, sans-serif",
"titleFontSize": 16,
"titleColor": "#252423",
"labelFont": "Segoe UI",
"labelFontSize": 13.333333333333332,
"labelColor": "#605E5C"
},
"legend": {
"titleFont": "Segoe UI",
"titleFontWeight": "bold",
"titleColor": "#605E5C",
"labelFont": "Segoe UI",
"labelFontSize": 13.333333333333332,
"labelColor": "#605E5C",
"symbolType": "circle",
"symbolSize": 75
}
},
"data": [{"name": "dataset"}],
"signals": [
{
"name": "cx",
"update": "width / 2"
},
{
"name": "cy",
"update": "height / 2"
},
{"name": "radius", "value": 8},
{"name": "collide", "value": 0.1},
{"name": "gravityX", "value": 0.2},
{"name": "gravityY", "value": 0.2},
{"name": "static", "value": true}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"domainMin": -100,
"domainMax": 140,
"domain": {
"data": "dataset",
"field": "__3__",
"sort": true
},
"range": "width"
},
{
"name": "yscale",
"type": "linear",
"range": "height",
"nice": true,
"domain": {
"data": "dataset",
"field": "__0__",
"sort": false
}
},
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "dataset",
"field": "__1__"
},
"range": {"scheme": "category20c"}
},
{
"name": "ballsize",
"domain": {
"data": "dataset",
"field": "__4__"
},
"range": [0, 50000]
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale"
},
{
"orient": "left",
"scale": "yscale",
"tickCount": 5,
"zindex": 1
}
],
"marks": [
{
"name": "nodes",
"type": "symbol",
"from": {"data": "dataset"},
"encode": {
"enter": {
"fill": {
"scale": "color",
"field": "__1__"
},
"xfocus": {
"scale": "xscale",
"field": "__3__",
"band": 0.5
},
"yfocus": {
"scale": "yscale",
"field": "__0__",
"band": 0.5
}
},
"update": {
"size": {
"scale": "ballsize",
"field": "__4__"
},
"stroke": {"value": "white"},
"strokeWidth": {"value": 1},
"zindex": {"value": 0},
"tooltip": {"signal": "datum"}
},
"hover": {
"stroke": {"value": "purple"},
"strokeWidth": {"value": 3},
"zindex": {"value": 1}
}
},
"transform": [
{
"type": "force",
"iterations": 100,
"forces": [
{
"force": "collide",
"iterations": {
"signal": "collide"
},
"radius": {
"expr": "sqrt(datum.size)/ 2"
}
},
{
"force": "x",
"x": "xfocus",
"strength": {
"signal": "gravityX"
}
},
{
"force": "y",
"y": "yfocus",
"strength": {
"signal": "gravityY"
}
}
]
}
]
},
{
"type": "text",
"from": {"data": "nodes"},
"encode": {
"enter": {
"align": {"value": "center"},
"baseline": {
"value": "middle"
},
"fontSize": {
"scale": "ballsize",
"field": "__4__"
},
"fontWeight": {
"value": "bold"
},
"fill": {"value": "black"},
"text": {
"field": "datum['__2__']"
}
},
"update": {
"x": {"field": "x"},
"y": {"field": "y"}
},
"transform": [
{
"type": "label",
"avoidMarks": ["nodes"],
"anchor": [
"top",
"bottom",
"right",
"left"
],
"offset": [1],
"size": {
"signal": "[width + 60, height]"
}
}
]
}
}
]
}





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

Proud to be a Super User!




Hi, this is beautiful work and much more than I requested.It will take a lot of time that I understand it and simplify for my use case.
Can you could help me to simplified it? I would be very thankful.
BR, Srđan

I was so in the weeds looking into circle packing that I completely forgot about the force transform 🤦🏻‍♂️. That should definitely work in the matrix format that you have. 

Since they brought it up, I'll defer to @KerKol, or @avatorl so one of them can get credit for the solution. I may just see if I can get it implemented on my own just for practice. 



Madison Giammaria
Proud to be a Super User 😄
LinkedIn

Do you frequently use Deneb to provide insights to your stakeholders? Have you considered sponsoring this free and open source custom visual? More info here!

Helpful resources

Announcements
Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount!

Dec Fabric Community Survey

We want your feedback!

Your insights matter. That’s why we created a quick survey to learn about your experience finding answers to technical questions.

ArunFabCon

Microsoft Fabric Community Conference 2025

Arun Ulag shares exciting details about the Microsoft Fabric Conference 2025, which will be held in Las Vegas, NV.

December 2024

A Year in Review - December 2024

Find out what content was popular in the Fabric community during 2024.

Top Kudoed Authors