Forum Discussion

Serizawa's avatar
Serizawa
New Member
1 month ago

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.



 

2 Replies

  • 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!




    • Serizawa's avatar
      Serizawa
      New 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:

      1. make _pris_saisi use the same program scope as _tout_AHT;

      2. compare each rate by entite_realisatrice in a normal Power BI table before looking at Deneb;

      3. inspect the remaining measures that may use other tables;

      4. 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.