J'essaie de calculer une moyenne mobile pour chaque ligne d'un tableau en fonction des valeurs présentes dans ce tableau en fonction d'une fenêtre de temps glissante en regardant en avant et en arrière un certain nombre de jours.

Étant donné le tableau suivant:

myTable
+------------+-------+
| Date       | Value |
+------------+-------+
| 31/05/2020 | 5     |
+------------+-------+
| 31/05/2020 | 10    |
+------------+-------+
| 01/06/2020 | 50    |
+------------+-------+
| 01/08/2020 | 50    |
+------------+-------+

Et la mesure

myMeasure =
VAR LookAheadAndBehindInDays = 28
RETURN
    AVERAGEX (
        DATESINPERIOD (
            myTable[Date],
            DATEADD ( LASTDATE ( myTable[Date] ), LookAheadAndBehindInDays, DAY ),
            -2 * LookAheadAndBehindInDays,
            DAY
        ),
        myTable[Value]
    )

J'ai vérifié que le DATESINPERIOD renvoie effectivement les bonnes dates. Mon problème réside dans le calcul de la moyenne.

Au lieu de calculer directement la moyenne de toutes les valeurs (résultat attendu)

+------------+-------+---------------------------+
| Date       | Value | myMeasure                 |
+------------+-------+---------------------------+
| 31/05/2020 | 5     | (5 + 10 + 50) / 3 = 21.66 |
+------------+-------+---------------------------+
| 31/05/2020 | 10    | (5 + 10 + 50) / 3 = 21.66 |
+------------+-------+---------------------------+
| 01/06/2020 | 50    | (5 + 10 + 50) / 3 = 21.66 |
+------------+-------+---------------------------+
| 01/08/2020 | 27    | 27 / 1 = 27               |
+------------+-------+---------------------------+

Il calcule d'abord la moyenne de chaque date, puis la moyenne de ces valeurs:

+------------+-------+--------------------+------------------------+
| Date       | Value | Avg. by Date       | myMeasure              |
+------------+-------+--------------------+------------------------+
| 31/05/2020 | 5     | (5 + 10) / 2 = 7.5 | (7.5 + 50) / 3 = 28.75 |
+------------+-------+--------------------+------------------------+
| 31/05/2020 | 10    | (5 + 10) / 2 = 7.5 | (7.5 + 50) / 3 = 28.75 |
+------------+-------+--------------------+------------------------+
| 01/06/2020 | 50    | 50 / 1 = 50        | (7.5 + 50) / 3 = 28.75 |
+------------+-------+--------------------+------------------------+
| 01/08/2020 | 27    | 27 / 1 = 27        | 27 / 1 = 27            |
+------------+-------+--------------------+------------------------+

J'ai découvert ce comportement en utilisant cette mesure:

myMeasure DEBUG =
VAR LookAheadAndBehindInDays = 28
VAR vTable =
    DATESINPERIOD (
        myTable[Date],
        DATEADD ( LASTDATE ( myTable[Date] ), LookAheadAndBehindInDays , DAY ),
        -2 * LookAheadAndBehindInDays,
        DAY
    )
RETURN
    FIRSTDATE ( vTable ) & " - " & LASTDATE ( vTable ) & UNICHAR(10) 
        & " - Row Count: " & COUNTROWS ( vTable )  & UNICHAR(10) 
        & " - Avg: " & AVERAGEX(vTable, myTable[Value]) & UNICHAR(10) 
        & " - Dates: " & CONCATENATEX ( vTable, myTable[Date], "," ) & UNICHAR(10) 
        & " - Values: " & CONCATENATEX ( vTable, myTable[Value], "," )

Cela renvoie pour les lignes avec la date '31 / 05/2020 'et '31 / 05/2020' la valeur suivante:

31/05/2020 - 01/06/2020
Row Count: 2
Avg: 28.75
Dates: 31/05/2020,01/06/2020
Values: 7.5,50

Les plus notables sont le nombre de lignes 2, que je m'attendrais à être 3 et les valeurs 5, 10 et 50 (comme indiqué ci-dessus dans les tableaux)

Ma question est donc de savoir comment calculer la moyenne mobile au fil du temps en pondérant chaque valeur de manière égale, au lieu de pondérer chaque jour de manière égale.

0
Jonas Marty 29 oct. 2020 à 16:04

2 réponses

Meilleure réponse

Je ne suis pas sûr d'avoir complètement compris le problème, mais pour moi, vous avez juste besoin d'une MOYENNE standard et non de l'itérateur AVERAGEX.

J'ai un peu changé la formule et je n'ai pas utilisé DATESINPERIOD, celle-ci obtient le même résultat et (pour moi) est plus claire et lisible

Avg =
VAR DaysInterval = 28
RETURN
    CALCULATE (
        AVERAGE ( myTable[Value] ),
        DATESBETWEEN (
            myTable[Date],
            MAX ( myTable[Date] ) - DaysInterval, --from
            MAX ( myTable[Date] ) + DaysInterval  --to
        )
    )

Voici le résultat (basé sur l'échantillon de données)

enter image description here

1
Giovanni Luisotto 29 oct. 2020 à 15:38

Ce que vous recherchez est la moyenne calculée à partir des jours - / + 28:

myMeasure = 
VAR LookAheadAndBehindInDays = 28
var curDAte = rolling[ Date]
return CALCULATE(AVERAGE(rolling[Value]), 
    FILTER(rolling,  
        rolling[ Date] +LookAheadAndBehindInDays >= curDAte && 
        rolling[ Date] -LookAheadAndBehindInDays <= curDAte))

Comme vous pouvez le voir, j'utilise le filtre pour obtenir les lignes comprises dans la plage de dates et calculer la moyenne sur celles-ci.

0
Aldert 1 nov. 2020 à 08:30