vega
10 TopicsDeneb: Develop Custom Visuals Inside Power BI
Building custom visuals in Power BI gives you total control over your scenario and results can be very rewarding. However, there's a high learning curve, particularly if you are not familiar with web development tools and technologies. If you already have experience with R and/or Python, Power BI offers visuals with an interface for you to write code in these languages, and these options can help a lot with producing tailor-made designs. Vega-Lite is a "visualization grammar" developed by the University of Washington Interactive Data Lab. It uses a declarative, JSON-based language that allows authors to build a range of bespoke visual designs with significantly less effort than coding from scratch. In this session, Daniel will introduce you to the Vega-Lite language via Deneb - a custom visual for Power BI. We will create some example visuals, as well as demonstrate some of the additional integration features with Power BI that aren't currently possible when using R & Python. ๐๐๐๐ฉ๐๐ฃ๐ ๐ก๐๐ฃ๐ (๐๐ ๐๐๐๐ข๐จ): https://bit.ly/3ri3kKf ๐๐๐ง๐จ๐๐๐ฃ ๐๐ฝ๐๐๐- ๐๐๐๐ง๐ค๐จ๐ค๐๐ฉ ๐พ๐ค๐ข๐ข๐ช๐ฃ๐๐ฉ๐ฎ: https://bit.ly/3IAg7xT ๐๐๐ฃ๐ ๐๐๐๐ฃ: https://bit.ly/32tGkif ๐๐๐ก๐๐๐ง๐๐ข ๐พ๐๐๐ฃ๐ฃ๐๐ก: https://t.me/PersianPBIUG ๐๐ค๐ช๐๐ช๐๐: https://bit.ly/3hk20RL Language: English1.5KViews0likes0CommentsDeneb, the star of data visualization
Deneb is a powerful visualisation tool, which allows us to build precise bespoke visualisation without the limitations of standard Power BI visuals. However there is a learning curve to overcome. This session helps break down that barrier and show the steps to being proficient in the required skills are not that steep. We will look at the first steps into Vega-Lite, one of the languages used in Deneb, and break down the basic components needed to build your first visuals and beyond. ๐๐๐ง๐จ๐๐๐ฃ ๐๐ฝ๐๐๐- ๐๐๐๐ง๐ค๐จ๐ค๐๐ฉ ๐พ๐ค๐ข๐ข๐ช๐ฃ๐๐ฉ๐ฎ: https://bit.ly/3IAg7xT ๐๐๐ฃ๐ ๐๐๐๐ฃ: https://bit.ly/32tGkif ๐๐๐ก๐๐๐ง๐๐ข ๐พ๐๐๐ฃ๐ฃ๐๐ก: https://t.me/PersianPBIUG ๐๐ค๐ช๐๐ช๐๐: https://bit.ly/3hk20RL Language: English132Views0likes0CommentsVega in Power BI โ positioning signals and custom sorting
Hello everyone, I just got a new book, "Before and After", and Iโm trying to recreate one of the visuals from it in Power BI using Vega. Iโve run into two challenges: I created a signal called EmploymentTypeMiddle and I want to position it dynamically at the middle of the first bin on the x-axis, regardless of the canvas width. Is this achievable in Vega? How can I sort the Region column in a custom, hard-coded order? I want the bars to appear in this sequence: Americas, Europe, Asia Pacific, Middle East & Africa. Here's my code Any suggestions?Power BI - Deneb/Vega 6.2.0: Filtering by Day Signal Causes Marks to Disappear
Hi everyone, I am building a real-time schedule visual in Vega. I have a working visual that shows all data, but it breaks when I try to filter for the current day. Data from provided from Power Bi to deneb: - DST_ClockDiffBtwLocationAndLocalOffset:This is a measure. TimeZone Difference. provides the offset of this difference. - From my Power BI table: - ScheduleType - day_num - type -startTime -endTime I have a query named AllSegments that creates a clean, flat table Each day, for each scheduleType, we can have multiple rows. For example: Scheduletype day_num type start_time end_time startTime endTime Production 0 No Production 00:00:00 22:00:00 0 22 Production 0 Normal 22:00:00 23:59:00 22 23.9833333 Production 1 Normal 00:00:00 23:59:00 0 23:9833333 ... SiteOpening 0 No Production 00:00:00 23:59:00 0 23.9833333 SiteOpening 1 Normal 08:30:00 12:30:00 8.5 12.5 SiteOpening 1 Normal 13:30 17:00:00 13.5 17 ... Support 0 No Production 00:00:00 23:59:00 0 23.9833333 Support 1 Normal 08:30:00 12:30:00 8.5 12.5 Support 1 Flexible 13:30:00 17:00:00 13.5 17 The goal is one graph with a 24 hours My working code: { "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "A static visual for Monday with a dynamic real-time clock.", "background": "transparent", "width": 360, "height": 80, "autosize": {"type": "fit", "contains": "padding"}, "signals": [ { "name": "timer", "update": "now()", "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}] }, { "name": "adjustedTime", "update": "length(data('source')) > 0 ? utcOffset('seconds', timer, data('source')[0].DST_ClockDiffBtwLocationAndLocalOffset) : now()" }, { "name": "currentTime", "update": "hours(adjustedTime) + minutes(adjustedTime) / 60" }, { "name": "adjustedDate", "update": "timeFormat(adjustedTime, '%Y-%m-%d')" } ], "data": [ { "name": "source" }, { "name": "dataset", "source": "source", "transform": [ { "type": "filter", "expr": "datum.ScheduleType == 'SiteOpening' && datum.type != 'No Production' && +datum.day_num == 1" } ] } ], "scales": [ { "name": "xscale", "type": "linear", "domain": [0, 24], "range": "width" } ], "axes": [ { "orient": "bottom", "scale": "xscale", "title": {"signal": "adjustedDate"}, "tickCount": 24, "labelFontSize": 8, "offset": 5 } ], "marks": [ { "type": "rect", "from": {"data": "dataset"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "x2": {"scale": "xscale", "field": "endTime"}, "y": {"value": 20}, "height": {"value": 30}, "fill": {"value": "lightgray"} } } }, { "type": "rule", "from": {"data": "dataset"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "y": {"value": 15}, "y2": {"value": 55}, "stroke": {"value": "black"}, "strokeWidth": {"value": 1} } } }, { "type": "symbol", "from": {"data": "dataset"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "y": {"value": 15}, "shape": {"value": "triangle-down"}, "size": {"value": 40}, "fill": {"value": "black"} } } }, { "type": "symbol", "from": {"data": "dataset"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "endTime"}, "y": {"value": 55}, "shape": {"value": "triangle-up"}, "size": {"value": 40}, "fill": {"value": "black"} } } }, { "type": "rule", "encode": { "update": { "x": {"scale": "xscale", "signal": "currentTime"}, "y": {"value": 10}, "y2": {"value": 60}, "stroke": {"value": "red"}, "strokeWidth": {"value": 2} } } }, { "type": "text", "encode": { "update": { "x": {"scale": "xscale", "signal": "currentTime"}, "y": {"value": 5}, "text": {"signal": "timeFormat(adjustedTime, '%H:%M')"}, "align": {"value": "center"}, "fill": {"value": "red"}, "fontSize": {"value": 10} } } } ] } Now, I want to filter these bars to show only the ones for the current day. I added a signals block for the current time and a filter to my data transform ... Code doesn't work: { "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "A dynamic, real-time visual for Site Opening Hours.", "background": "transparent", "width": 360, "height": 80, "autosize": {"type": "fit", "contains": "padding"}, "signals": [ { "name": "timer", "update": "now()", "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}] }, { "name": "adjustedTime", "update": "length(data('source')) > 0 ? utcOffset('seconds', timer, data('source')[0].DST_ClockDiffBtwLocationAndLocalOffset) : now()" }, { "name": "currentTime", "update": "hours(adjustedTime) + minutes(adjustedTime) / 60" }, { "name": "adjustedDate", "update": "timeFormat(adjustedTime, '%Y-%m-%d')" }, { "name": "currentDayNum", "update": "day(adjustedTime)" } ], "data": [ { "name": "source" }, { "name": "opening_hours_today", "source": "source", "transform": [ { "type": "filter", "expr": "datum.ScheduleType == 'SiteOpening' && datum.type != 'No Production' && +datum.day_num == currentDayNum" } ] } ], "scales": [ { "name": "xscale", "type": "linear", "domain": [0, 24], "range": "width" } ], "axes": [ { "orient": "bottom", "scale": "xscale", "title": {"signal": "adjustedDate"}, "tickCount": 24, "labelFontSize": 8, "offset": 5 } ], "marks": [ { "type": "rect", "from": {"data": "opening_hours_today"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "x2": {"scale": "xscale", "field": "endTime"}, "y": {"value": 20}, "height": {"value": 30}, "fill": {"value": "lightgray"} } } }, { "type": "rule", "from": {"data": "opening_hours_today"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "y": {"value": 15}, "y2": {"value": 55}, "stroke": {"value": "black"}, "strokeWidth": {"value": 1} } } }, { "type": "symbol", "from": {"data": "opening_hours_today"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "startTime"}, "y": {"value": 15}, "shape": {"value": "triangle-down"}, "size": {"value": 40}, "fill": {"value": "black"} } } }, { "type": "symbol", "from": {"data": "opening_hours_today"}, "encode": { "enter": { "x": {"scale": "xscale", "field": "endTime"}, "y": {"value": 55}, "shape": {"value": "triangle-up"}, "size": {"value": 40}, "fill": {"value": "black"} } } }, { "type": "rule", "encode": { "update": { "x": {"scale": "xscale", "signal": "currentTime"}, "y": {"value": 10}, "y2": {"value": 60}, "stroke": {"value": "red"}, "strokeWidth": {"value": 2} } } }, { "type": "text", "encode": { "update": { "x": {"scale": "xscale", "signal": "currentTime"}, "y": {"value": 5}, "text": {"signal": "timeFormat(adjustedTime, '%H:%M')"}, "align": {"value": "center"}, "fill": {"value": "red"}, "fontSize": {"value": 10} } } } ] } the final goal is: - real time current clock (red bar + current hour text) - real time current day. if it is a production day, a blue rect align on the 24 hours, if it is Flexible period, a dark blue rect. if No prod, a gray rect - A second bar to provide info about when the location can have a support - a legend with the different info Thanks a lot for the support you will accept to provideSolvedBugs in my customized version of a popular gantt chart
Hello Community, Iโve been working on developing a Gantt chart using Madison Giammariaโs giammariam template. It is great already but I had to develop some other custom features so Iโve successfully implemented several functionalitiesโpartly using my own knowledge and partly with AI assistance. However, Iโve now hit a roadblock with three bugs that are preventing the visual from functioning as intended. Iโd love any help in resolving themโfixing just one would be a great step forward, but solving all three would be a huge relief! ๐ Bug 1: Expanding/Collapsing Tasks in Bulk I wanted to create a custom bulk expand/collapse button to toggle all tasks at once. However, unlike the original template, if I expand all tasks and then try to collapse just one, it collapses all of them instead of only the selected one. I suspect the issue lies in the hierarchy_initial transformations (lines 2224โ2238) in my Vega code, but I havenโt been able to get it working as intended. Bug 2: Horizontal Scrolling, Zooming, and Task Visibility Issues I had to tweak the template to properly display the Today line, as I couldnโt get it working from the original setup. However, my implementation may have introduced unexpected issues. Problem 1: Tasks Not Visible in Default View For example, in the image below, Task 95 (starting on March 19, 2023) should be partially visible, but it isnโt. If I scroll horizontally or zoom out slightly, it suddenly appears. Expanding the task doesnโt reveal the subtasks either. I suspect the issue is related to how the x-axis range is set before and after the min/max task dates. I attempted to configure default views for different task lengths using the configDateStepSizePercentInitial signal (lines 25โ28), but that didnโt resolve it. Problem 2: Missing Tasks on Horizontal Scroll If I scroll left (Shift + Mouse Wheel), I expect to see tasks from 2022, but they donโt appear even though they should. This is my biggest issueโif anyone has insights on what might be causing this, Iโd be incredibly grateful! Bug 3: Bottom Tasks Not Expandable This issue also exists in the original template: If the last task in the visual reaches the bottom of the canvas, the task is not clickable, preventing expansion. The only workaround is to collapse some other tasks first, but that negatively affects the user experience. Iโd really appreciate any advice, guidance, or fixes for these issues. Even just pointing me in the right direction would be incredibly helpful. Sample file: https://www.dropbox.com/scl/fi/dcrciewmls9dj3fqpc4m8/sample_data_tasks.pbix?rlkey=65tjgo587u9991jaj7t4j2y3s&st=r5j7jh0n&dl=0 Thanks in advance, and have a great day! PetrDeneb grid
I want to create a grid that should display images in base64 format from my table. The idea is that the spaces (and therefore the images) should grow as I filter the data, always filling the canvas with images (so if I select just one image, the canvas is basically one image. If I filter by a group of 100 images, the code should split the canvas evenly across 100 cells). Currently I have a grid where I can display images. If I don't filter, it looks fine, but not all images are displayed. (see 1. screenshot) If I filter for a group with many images, it works, the size of the images grows and there are fewer cells, but it seems to keep the space of the filtered out image. (see 2. screenshot) When I filter for a group with only a few images, it stops working and I get a blank canvas again. I can't figure out what the problem is, as it works to some extent, but not completely. I would appreciate any help or ideas. Here is my Vega code: { "$schema": "https://vega.github.io/schema/vega/v5.json", "width": 1100, "height": 600, "data": [ { "name": "dataset", "format": {"type": "json"}, "url": "data:dataset" // Load filtered data from Power BI } ], "signals": [ { "name": "filteredDatasetLength", "update": "data('dataset').length" // Track the length of the filtered dataset }, { "name": "gridSize", "update": "filteredDatasetLength > 0 ? ceil(sqrt(filteredDatasetLength)) : 0" // Grid size adjusts based on available data }, { "name": "cellSize", "update": "filteredDatasetLength > 0 ? ceil((width - 20) / gridSize) : 0" // Dynamic cell size based on grid size } ], "marks": [ { "type": "image", "from": {"data": "dataset"}, "encode": { "enter": { "url": {"field": "Base64:"}, // Use the Base64 column for images "x": { "signal": "cellSize * (datum.Index % gridSize) + 10" // Dynamic calculation of X position based on index and grid size }, "y": { "signal": "cellSize * floor(datum.Index / gridSize) + 10" // Dynamic calculation of Y position based on index and grid size }, "width": {"signal": "cellSize - 5"}, // Image width adjusted to fit in grid "height": {"signal": "cellSize - 5"} // Image height adjusted to fit in grid } } } ] }advanced cross filtering with deneb and vega - brushed area disappearing when doing cross filter
My report has a deneb vega line chart and a table. I want to filter the table by brushing the chart and then clicking on the brushed area. The idea is to only apply cross filtering when required. PBIX file The filter works partially: (1) brushing on the area works as expected: (2) Then clicking on the brushed area filters the table: However the brushed area disappears. I'd like to keep the brushed area after the click. I've tried different debounce, throttle and consume values for the event - not sure what is causing the brushed area to disappear. { "data": [ { "name": "dataset" } ], "width": 200, "height": 200, "signals": [ { "name": "colour", "value": "blue" }, // brush { "name": "brush", "value": 0, "on": [ { "events": "@main:pointerdown", "update": "[x(), x()]" }, { "events": "[@main:pointerdown, window:pointerup] > window:pointermove!", "update": "[brush[0], clamp(round(x()-brush[0])+brush[0], 0, width)]" }, { "events": { "signal": "delta" }, "update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)" } ] }, // anchor { "name": "anchor", "value": null, "on": [ { "events": "@brush:pointerdown", "update": "slice(brush)" } ] }, // xdown { "name": "xdown", "value": 0, "on": [ { "events": "@brush:pointerdown", "update": "x()" } ] }, // delta { "name": "delta", "value": 0, "on": [ { "events": "[@brush:pointerdown, window:pointerup] > window:pointermove!", "update": "x() - xdown" } ] }, // main_brush { "name": "main_brush", // "push": "outer", "on": [ { "events": { "signal": "brush" }, "update": "span(brush) ? invert('x_scale', brush) : null" } ] }, // cross filter start ------------------------------------------ { "name": "pbiCrossFilterSelection", "value": [], "on": [ // when mark is brushed apply cross filter { "events": { "markname": "brush", "type": "click", "consume": true, "debounce": 100, "throttle": 100 }, "update": "pbiCrossFilterApply(event, \"datum['x'] >= main_brush[0] & datum['x'] <= main_brush[1]\" )" } ] } // cross filter end ------------------------------------------ ], "scales": [ { "name": "x_scale", "range": "width", "padding": 10, "domain": { "data": "dataset", "field": "x" } }, { "name": "y_scale", "range": "height", "padding": 10, "domain": { "data": "dataset", "field": "y" } } ], "axes": [ { "orient": "bottom", "scale": "x_scale" }, { "orient": "left", "scale": "y_scale" } ], "marks": [ { "name": "main", "type": "group", "encode": { "enter": { "x": { "value": 0 }, "y": { "value": 0 }, "height": { "value": 200 }, "width": { "value": 200 }, "fill": { "value": "transparent" } } }, "marks": [ // main line chart { "name": "main_line", "type": "line", "from": { "data": "dataset" }, "encode": { "enter": { "x": { "scale": "x_scale", "field": "x" }, "y": { "scale": "y_scale", "field": "y" } }, "update": { "stroke": { "signal": "colour" } } } }, // brush area mark { "type": "rect", "name": "brush", "encode": { "enter": { "y": { "value": 0 }, "height": { "value": 200 }, "fill": { "value": "#333" }, "fillOpacity": { "value": 0.2 } }, "update": { "x": { "signal": "brush[0]" }, "x2": { "signal": "brush[1]" } } } } ] } ] }SolvedNavigation + Filtering in a custom Deneb Vega visual
Dear reader, I'm a consultant currently working on a Power BI dashboard which has required me to include a custom visualization. For this I used a Gantt Chart template created by David Bacci (see Deneb-Showcase/Gantt Chart at main ยท PBI-David/Deneb-Showcase ยท GitHub for the code) The standard template looks as follows: The client is asking me to implement a feature that allows users to select a value in the "Tasks" column, e.g. "Story boarding", and navigate to another page with a tailored view based on this selection. So, for example, one would click on "Story boarding" in the column and the dashboard will then navigate to another tab. And in this tab the visuals will be filtered such that "Task == Story boarding". I have discussed within my team that this is likely impossible, but we wanted to know for sure. An alternative solution is of course also welcome! Unfortunately, an invisible button overlay will not work, because in our case there will be a lot of rows and scrolling will be required. Besides, the visual will be dynamically updated. Thanks a lot in advance! ๐Power of Deneb-Vega: The US Presidential Election Chart (chart example with JSON code)
After all the struggle with native Power BI visuals (their limitations) Deneb-Vega gives you a real power. Probably for someone who worked with JavaScript from the beginning itโs nothing special, but for a Power BI developer itโs a whole new world inside of Power BI. Highly customizable and interactive world of data visualization. I wanted to build this chart in 2020 during the US elections, but I had no tool (inside of Power BI) and knowledge (Vega) to achieve required conditional formatting and interactivity. Now I can build highly customized and highly interactive charts in Power BI. And what is great, itโs possible to publish the same chart on the web without Power BI. The charts show the elections result, but also allows a user to flip states/districts (by clicking on a gray horizontal bar) to see how different result in this state/district could affect the overall result. The chart could be very useful during the vote counting, when most results are already known, but a few states/districts are still counting the votes. But I have missed the 2020 elections and made the chart 2 years later. Well, soon it will be useful again. Also itโs a great showcase of a good data visualization and a great showcase of Deneb-Vega possibilities. Live Power BI report with the chart: https://powerofbi.org/2022/10/27/us-presidential-elections-chart/ Vega JSON code: https://github.com/avatorl/Deneb-Vega/tree/main/US%20Elections%20Chart