Forum Discussion
Deneb/vega on power bi
Hello,
I am building a radar chart in Power BI using Deneb with Vega. The chart displays seven indicators:
- Precarious work rate
- AHT stability
- AHT entry rate
- AHT consumption
- AJT entry rate
- AJT consumption
- Window consumption
I created a disconnected configuration table in DAX:
t_radar_Indicateurs =
DATATABLE(
"Indicateur", STRING,
"Ordre", INTEGER,
"Seuil", DOUBLE,
"Sens", STRING,
{
{"Taux de précaires", 1, 0.10, "MAX"},
{"Stab AHT", 2, 0.85, "MIN"},
{"Saisie AHT", 3, 0.92, "MIN"},
{"Consommation AHT", 4, 0.75, "MIN"},
{"Taux de saisie AJT", 5, 0.92, "MIN"},
{"Consommation AJT", 6, 0.90, "MIN"},
{"Tx consommation Fenêtres", 7, 0.92, "MIN"}
}
)
This table contains four columns:
- Indicateur
- Ordre
- Seuil
- Sens
The actual rate is returned by a separate measure using SELECTEDVALUE and SWITCH, depending on the selected indicator.
The Deneb dataset therefore receives fields such as:
- Indicateur
- Ordre
- Sens
- Taux
- Objectifs
My Vega specification converts decimal percentage values such as 0.92 into 92, and keeps values already expressed as percentages.
The radial scale is defined as:
{
"name": "r",
"type": "linear",
"domain": [0, 100],
"range": [0, {"signal": "radius"}]
}
I currently have two main issues.
1. One indicator displays 176.7%
The “AHT entry rate” indicator is displayed as 176.7%.
In the Vega code, the displayed value comes directly from datum.TauxNum, so Vega does not seem to create this value by itself. It appears to be receiving either 1.767 or 176.7 from Power BI.
However, this indicator is supposed to represent a rate, and I am not sure whether this result is legitimate or caused by:
- duplicate rows in the numerator;
- the use of COUNT instead of DISTINCTCOUNT;
- different filter contexts between numerator and denominator;
- an incorrect relationship in the Power BI model;
- a measure removing filters with ALL or REMOVEFILTERS.
Because the Vega radial domain stops at 100, the 176.7% point is also drawn outside the radar.
What would be the best way to diagnose whether the issue comes from the DAX measure, the model relationships, or the Vega percentage conversion?
2. Several radars show identical values for different entities
I display several radar charts for different operational entities. Some of them show exactly the same values even though the entities should have different results.
The entity filter uses:
't_pbi_dash'[entite_realisatrice]
The indicator configuration table is disconnected, which I understand is normal because it is only used to select the appropriate measure through SWITCH.
My concern is that one or more measures selected by the SWITCH may not preserve the entity filter context.
The measures used include:
_tx_precaire
_tx_stabiliteAHT_All
_tx_saisie_sur_AHT
_tx_pris_AHT
_tx_prises_sur_ajt
_Tx_fenêtres_prises
Could identical radars be caused by:
- missing relationships between the business tables and the entity table;
- inactive or incorrect relationships;
- measures using columns from different entity tables;
- ALL, REMOVEFILTERS or similar functions inside the measures;
- the disconnected radar table;
- the way Deneb groups the dataset?
What debugging measures or temporary table visual would you recommend to verify the filter context received by each measure for each entity?
I can provide the complete Vega specification and the DAX measures if needed.
3 Replies
- BeaBF
Super User
Serizawa Hi!
The disconnected indicator table is correct and does not need a relationship. The issue is more likely that the measures used in the SWITCH do not all receive the filter from 't_pbi_dash'[entite_realisatrice].As a first test, I would explicitly pass the selected entity to the fact table used by each measure with TREATAS:
Radar Value =
VAR _Indicator =
SELECTEDVALUE ( t_radar_Indicateurs[Indicateur] )VAR _Entities =
VALUES ( 't_pbi_dash'[entite_realisatrice] )RETURN
SWITCH (
_Indicator,"Taux de précaires",
CALCULATE (
[_tx_precaire],
KEEPFILTERS (
TREATAS (
_Entities,
'FactPrecaire'[entite_realisatrice]
)
)
),"Stab AHT",
CALCULATE (
[_tx_stabiliteAHT_All],
KEEPFILTERS (
TREATAS (
_Entities,
'FactAHT'[entite_realisatrice]
)
)
),"Saisie AHT",
CALCULATE (
[_tx_saisie_sur_AHT],
KEEPFILTERS (
TREATAS (
_Entities,
'FactAHT'[entite_realisatrice]
)
)
),"Consommation AHT",
CALCULATE (
[_tx_pris_AHT],
KEEPFILTERS (
TREATAS (
_Entities,
'FactAHT'[entite_realisatrice]
)
)
),"Taux de saisie AJT",
CALCULATE (
[_tx_prises_sur_ajt],
KEEPFILTERS (
TREATAS (
_Entities,
'FactAJT'[entite_realisatrice]
)
)
),"Consommation AJT",
CALCULATE (
[_tx_consommation_ajt],
KEEPFILTERS (
TREATAS (
_Entities,
'FactAJT'[entite_realisatrice]
)
)
),"Tx consommation Fenêtres",
CALCULATE (
[_Tx_fenêtres_prises],
KEEPFILTERS (
TREATAS (
_Entities,
'FactFenetres'[entite_realisatrice]
)
)
)
)
The fact-table and column names must obviously be replaced with the actual ones. If this measure produces different radars, it confirms that the entity filter was not propagating to all the tables. The permanent solution would be to create a shared entity dimension related one-to-many to every fact table and use the entity field from that dimension in the visual.For the 176.7%, I would check the AHT measure directly. It should return a decimal ratio and should not multiply by 100:
_tx_saisie_sur_AHT =
DIVIDE (
[Distinct AHT Entries],
[Distinct Expected AHT],
BLANK()
)
For example:
Distinct AHT Entries =
DISTINCTCOUNT ( 'FactAHT'[AHT_ID] )Distinct Expected AHT =
DISTINCTCOUNT ( 'FactAHTExpected'[AHT_ID] )
If the numerator and denominator come from different tables, make sure they are both filtered by the same entity dimension. If the expected AHT table is not filtered by entity, apply the same entity filter with TREATAS.I would then remove the conditional percentage conversion from Vega. Keep both measures and thresholds as decimals, use:
{
"name": "r",
"type": "linear",
"domain": [0, 1],
"range": [0, {"signal": "radius"}],
"clamp": true
}
and format the label with:
"format(datum.Taux, '.1%')"
If _tx_saisie_sur_AHT returns 1.767, then 176.7% is the real DAX result. In that case, the numerator is greater than the denominator, most likely because of duplicated AHT identifiers, different grains, or different filter contexts. Vega is only displaying the value it receives.
💡 Did I answer your question? Mark my post as a solution!
👍 Kudos are appreciated
🔥 Proud to be a Super User!
- SerizawaNew Member
Thank you, this is very helpful.
I checked the DAX behind the measures, and I have a bit more information now.
For the entity-filter issue, most of the measures involved are actually calculated directly from the same fact table, t_pbi_dash, which is also the table containing the entity field used in the visual:
't_pbi_dash'[entite_realisatrice]
For example:
_tx_prises_sur_ajt = DIVIDE([_pris], [_tout_ajt], 0)
with:
_pris = VAR DateDebut = MIN('t_pbi_sequence_date'[date_serie]) VAR DateFin = MAX('t_pbi_sequence_date'[date_serie]) RETURN COALESCE( CALCULATE( COUNTA('t_pbi_dash'[id_op]), 't_pbi_dash'[prise], 't_pbi_dash'[titulaire_ou_associee], 't_pbi_dash'[date_ajt_fin] >= DateDebut, 't_pbi_dash'[date_ajt] <= DateFin ), 0 )and:
_tout_ajt = VAR DateDebut = MIN('t_pbi_sequence_date'[date_serie]) VAR DateFin = MAX('t_pbi_sequence_date'[date_serie]) RETURN COALESCE( CALCULATE( COUNTA('t_pbi_dash'[id_op]), 't_pbi_dash'[titulaire_ou_associee], 't_pbi_dash'[date_ajt_fin] >= DateDebut, 't_pbi_dash'[date_ajt] <= DateFin ), 0 )The same is true for _pris_saisi, _pris_aht, _precaire, etc. They all reference t_pbi_dash directly and do not currently use ALL, REMOVEFILTERS, or another unrelated fact table.
Because of that, I am now less convinced that TREATAS is necessary for these particular measures, since the filter on t_pbi_dash[entite_realisatrice] should already be part of the filter context.
I will still check the remaining measures, especially _stab_AHT and _Tx_fenêtres_prises, because those may use other tables.
Regarding the 176.7% value, I think I found a likely cause.
The rate is:
_tx_saisie_sur_AHT = DIVIDE([_pris_saisi], [_tout_AHT], 0)
with:
_tout_AHT = [_tout_ajt] - [_hors_prgm]
However, _pris_saisi currently includes rows that are outside the program:
_pris_saisi = VAR DateDebut = MIN('t_pbi_sequence_date'[date_serie]) VAR DateFin = MAX('t_pbi_sequence_date'[date_serie]) RETURN COALESCE( CALCULATE( COUNTA('t_pbi_dash'[id_op]), 't_pbi_dash'[pris_pas_pris_saisi], 't_pbi_dash'[titulaire_ou_associee], 't_pbi_dash'[date_ajt_fin] >= DateDebut, 't_pbi_dash'[date_ajt] <= DateFin ), 0 )So the numerator can contain “hors programme” rows while the denominator explicitly removes them.
In other words, the current calculation is effectively:
entered AHT, including out-of-program rows ------------------------------------------ total AHT excluding out-of-program rows
That seems like a plausible explanation for a value greater than 100%.
My next steps are therefore:
make _pris_saisi use the same program scope as _tout_AHT;
compare each rate by entite_realisatrice in a normal Power BI table before looking at Deneb;
inspect the remaining measures that may use other tables;
only use TREATAS where the entity filter genuinely needs to be propagated to another table.
So at this stage, Vega seems unlikely to be the source of either issue: the 176.7% appears to come from the DAX ratio itself, and the identical radars may only concern some of the measures rather than all of them.
- BeaBF
Super User
Hi Serizawa ,
Thanks for sharing the measures. Your diagnosis is right. Here are a few points to help you close both issues.
- The 176.7%
The numerator and the denominator don't count the same set of rows. _tout_AHT removes the out-of-programme rows, but _pris_saisi doesn't, so the ratio can go above 100%. The safest fix is to apply the same scope to both sides, in the same way:
_pris_saisi_hors_prgm =
VAR DateDebut = MIN ( 't_pbi_sequence_date'[date_serie] )
VAR DateFin = MAX ( 't_pbi_sequence_date'[date_serie] )
RETURN COALESCE ( CALCULATE ( COUNTA ( 't_pbi_dash'[id_op] ), 't_pbi_dash'[pris_pas_pris_saisi], 't_pbi_dash'[titulaire_ou_associee], 't_pbi_dash'[date_ajt_fin] >= DateDebut, 't_pbi_dash'[date_ajt] <= DateFin, <same out-of-programme condition used in _hors_prgm> ), 0 ) _pris_saisi_prgm = [_pris_saisi] - [_pris_saisi_hors_prgm] _tx_saisie_sur_AHT = DIVIDE ( [_pris_saisi_prgm], [_tout_AHT] )Also check these:
- _hors_prgm must use exactly the same filters as _tout_ajt (titulaire_ou_associee and the date overlap). If it doesn't, the subtraction mixes two scopes, and the denominator can end up too small.
- COUNTA vs DISTINCTCOUNT. COUNTA('t_pbi_dash'[id_op]) counts rows, not operations. If an id_op can appear on more than one row (one row per date, status or person, for example), compare COUNTROWS with DISTINCTCOUNT('t_pbi_dash'[id_op]) for one entity. If the two numbers differ, use DISTINCTCOUNT in both the numerator and the denominator.
- A temporary check measure shows you every place where the issue remains: Check AHT = IF ( [_pris_saisi_prgm] > [_tout_AHT], "Numerator > Denominator" )
- Identical radars
You're right: measures built only on t_pbi_dash already receive the filter on 't_pbi_dash'[entite_realisatrice], so they don't need TREATAS. That points the identical values at three possible causes:
- Measures that read other tables (_stab_AHT, _Tx_fenêtres_prises). Those tables can't be filtered by a column that lives in another fact table, so they return the same total for every entity. That's exactly the "same value on several radars" symptom, and those are the measures where TREATAS (or a shared dimension) is needed.
- The entity used in the slicer, the visual filter or the Deneb field well comes from a table other than t_pbi_dash.
- The relationship between t_pbi_sequence_date and t_pbi_dash. If one exists, its filter combines with your date-overlap condition. If the date table is meant only to define the period, keep it disconnected.
To diagnose quickly, build a matrix with entite_realisatrice on rows and t_radar_Indicateurs[Indicateur] on columns, use your Radar Value measure, and add these two debug measures:
Debug Entity = CONCATENATEX ( VALUES ( 't_pbi_dash'[entite_realisatrice] ), 't_pbi_dash'[entite_realisatrice], ", " ) Debug Rows = COUNTROWS ( 't_pbi_dash' )
Any column of the matrix that shows the same value on every row is a measure that isn't responding to the entity.
Long-term: create an Entite dimension table related one-to-many to t_pbi_dash and to every other fact table, and use its column in the visuals and slicers. You can then drop TREATAS completely.
- Deneb
Once the DAX is fixed, Vega only needs to display the decimal value it receives, with no conditional ×100 conversion:
- Use "domain": [0, 1] with "clamp": true.
- Format the labels with format(datum.Taux, '.1%').
If you'd rather show an overshoot above 100% than cut it off, set the domain maximum to max(1, the largest value in the data) instead of clamping.
I agree with you that Vega isn't the source of either issue. Fixing the DAX scope and checking the measures in a normal table first is the right order.
BBF