Reputation: 724
I'm trying to make a Deneb Gantt chart, but I'd like to show the Projects grouped by Assignee ( quite the same way as if I had a Power BI table and I'd stack both Assignee and Project on rows, I could see all the Assignee's projects by clicking the +/- -sign and opening the row)
I now have the Assignees on the y-axis and tasks as ranged bars, but as you can see, it's really confusing (for Assignee 1) if the projects aren't listed on the y-axis as well. I've tried to make facets but I've had zero luck. Are facets even possible with Gantt charts, or how should I go around with this?
Example data:
Project | Task | Assignee | StartDate | EndDate |
---|---|---|---|---|
Project1 | Task1 | Assignee1 | 01/05/2023 | 30/06/2023 |
Project1 | Task1 | Assignee2 | 01/04/2023 | 31/05/2023 |
Project1 | Task2 | Assignee3 | 01/07/2023 | 14/07/2023 |
Project2 | Task1 | Assignee1 | 01/07/2023 | 31/07/2023 |
Example code:
{
"title": {
"text": "Title",
"fontSize": 16,
"color": "#34282C"
},
"data": {"name": "dataset"},
"layer": [
{
"transform": [
{
"calculate": "now()",
"as": "Today"
}
],
"mark": {
"type": "rule",
"color": "Sienna",
"strokeDash": [0, 0],
"size": 1,
"tooltip": true
},
"encoding": {
"x": {
"field": "Today",
"type": "temporal"
}
}
},
{
"layer": [
{
"params": [
{
"name": "grid",
"select": "interval",
"bind": "scales"
},
{
"name": "highlight",
"select": {
"type": "point",
"on": "mouseover"
}
},
{
"name": "select",
"select": "point"
}
],
"mark": {
"type": "bar",
"opacity": 1,
"cornerRadius": 6,
"height": 25,
"tooltip": true,
"color": "#FFFFFF"
}
},
{
"mark": {
"type": "bar",
"opacity": 0.6,
"cornerRadius": 6,
"height": 20,
"tooltip": true,
"stroke": "black"
},
"encoding": {
"color": {
"field": "Assignee",
"legend": null
}
}
},
{
"mark": {
"type": "text",
"align": "left",
"dx": 5,
"fontSize": 12
},
"encoding": {
"text": {
"field": "Task",
"type": "nominal"
}
}
}
],
"encoding": {
"y": {
"field": "Assignee",
"type": "ordinal",
"axis": {
"title": null,
"grid": true,
"gridWidth": 2,
"tickBand": "extent",
"labelFontSize": 15,
"labelColor": "#34282C",
"zindex": 1
}
},
"x": {
"field": "StartDate",
"type": "temporal",
"axis": {
"title": null,
"format": "%m/%y",
"labelExpr": "[timeFormat(datum.value, '%m/%y'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']",
"orient": "top",
"grid": true,
"gridWidth": 2,
"gridColor": "#ddd",
"gridDash": {
"condition": {
"test": {
"field": "value",
"timeUnit": "month",
"equal": 1
},
"value": []
},
"value": [2, 2]
},
"labelOffset": 15,
"labelAlign": "left",
"labelPadding": 0
}
},
"x2": {"field": "EndDate"},
"yOffset": {
"field": "Assignee"
},
"fillOpacity": {
"condition": {
"param": "select",
"value": 1
},
"value": 0.3
},
"strokeWidth": {
"condition": [
{
"param": "select",
"empty": false,
"value": 2
},
{
"param": "highlight",
"empty": false,
"value": 1
}
],
"value": 0
}
}
}
]
}
Example plot:
Upvotes: 1
Views: 2270
Reputation: 2441
How does something like this look?
As you can see I added a transform to concatenate the data. This way it sorts nicely. Then I extract just part of this as the axis label and also color by Assignee.
{
"calculate": "datum.Assignee + ' | ' + datum.Project + '/' + datum.Task + ' | Start:' + utcFormat(datum.start,'%B %d, %Y') + ' #' + datum.running_number",
"as": "project_full_descr"
}
Full spec for the vega-lite community:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": 600,
"data": {
"values": [
{
"Project": "Project1",
"Task": "Task1",
"Assignee": "Assignee1",
"start": "2023-05-01",
"end": "2023-06-01"
},
{
"Project": "Project1",
"Task": "Task1",
"Assignee": "Assignee2",
"start": "2023-04-01",
"end": "2023-05-01"
},
{
"Project": "Project1",
"Task": "Task2",
"Assignee": "Assignee3",
"start": "2023-07-01",
"end": "2023-07-14"
},
{
"Project": "Project2",
"Task": "Task1",
"Assignee": "Assignee1",
"start": "2023-07-01",
"end": "2023-08-01"
}
]
},
"transform": [
{"calculate": "toDate(utcFormat(now(), '%Y-%m-%d'))", "as": "currentDate"},
{
"window": [{"op": "row_number", "as": "running_number"}],
"groupby": ["Assignee"],
"sort": [{"field": "start"}]
},
{
"calculate": "datum.Assignee + ' | ' + datum.Project + '/' + datum.Task + ' | Start:' + utcFormat(datum.start,'%B %d, %Y') + ' #' + datum.running_number",
"as": "project_full_descr"
}
],
"title": {
"text": "Order Gantt by: Assignee > Project > Task",
"fontSize": 14,
"anchor": "start",
"dy": -15,
"color": "#706D6C"
},
"layer": [
{
"mark": {
"type": "bar",
"tooltip": true,
"cornerRadiusTopRight": 4,
"cornerRadiusBottomRight": 4
},
"encoding": {
"y": {
"field": "project_full_descr",
"type": "nominal",
"axis": {
"domain": true,
"grid": false,
"ticks": true,
"labels": true,
"labelLimit": 800,
"labelFontSize": 12,
"labelPadding": 10,
"labelExpr": "split(datum.label, '|')[1]"
},
"title": null
},
"x": {
"field": "start",
"type": "temporal",
"timeUnit": "yearmonthdate",
"axis": null,
"title": null
},
"x2": {"field": "end"},
"color": {
"title": null,
"field": "Assignee",
"type": "nominal",
"legend": null
}
}
},
{
"mark": {"type": "rule", "strokeDash": [2, 2], "strokeWidth": 2},
"encoding": {
"x": {
"field": "currentDate",
"type": "temporal",
"axis": {"format": "%d-%b"}
}
}
},
{
"mark": {
"type": "text",
"align": "right",
"dx": -24,
"dy": 0,
"fontSize": 9
},
"encoding": {
"x": {"field": "start"},
"y": {"field": "project_full_descr", "type": "nominal"},
"text": {"field": "start", "type": "temporal", "format": "%d-%b"},
"color": {"value": "white"}
}
},
{
"mark": {
"type": "text",
"align": "left",
"dx": 5,
"dy": 0,
"fontSize": 9
},
"encoding": {
"x": {"field": "end"},
"y": {"field": "project_full_descr", "type": "nominal"},
"text": {"field": "end", "type": "temporal", "format": "%d-%b"},
"color": {"value": "black"}
}
}
],
"config": {"view": {"stroke": null}}
}
Happy charting!
Adam
Upvotes: 0
Reputation: 30174
I have created a Deneb Gantt chart in Vega already - you can see here. Can you reuse the logic from that?
https://github.com/PBI-David/Deneb-Showcase
Upvotes: 2