Скользящее среднее по времени с несколькими значениями на дату

#powerbi #powerbi-desktop

#powerbi #powerbi-рабочий стол

Вопрос:

Я пытаюсь рассчитать скользящее среднее для каждой строки таблицы на основе значений, присутствующих в этой таблице, на основе скользящего временного окна, просматривающего вперед и назад определенное количество дней.

Учитывая следующую таблицу:

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

и мера

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

Я проверил, что DATESINPERIOD возвращает фактически правильные даты. Моя проблема заключается в вычислении среднего значения.

Вместо прямого вычисления среднего значения всех значений (ожидаемый результат)

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

Сначала вычисляется среднее значение для каждой даты, а затем среднее значение этих значений:

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

Я узнал об этом поведении, используя эту меру:

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

Это возвращает для строк с датой ’31/05/2020′ и ’31/05/2020′ следующее значение:

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

Наиболее примечательными являются количество строк 2, которое, как я ожидал, будет равно 3, и значения 5,10 и 50 (как указано выше в таблицах)

Итак, мой вопрос в том, как можно рассчитать скользящее среднее по времени, взвешивая каждое значение одинаково, вместо того, чтобы взвешивать каждый день одинаково.

Ответ №1:

Я не уверен, что полностью понял проблему, но для меня вам просто нужно стандартное среднее значение, а не итератор AVERAGEX.

Я немного изменил формулу и не использовал DATESINPERIOD, этот дает тот же результат и (для меня) более понятен и удобочитаем

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

  

вот результат (основанный на образце набора данных)

введите описание изображения здесь

Ответ №2:

То, что вы ищете, — это вычисленное среднее значение за дни — / 28:

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

как вы можете видеть, я использую фильтр, чтобы получить строки, попадающие в диапазон дат, и вычислить среднее значение по ним.

Комментарии:

1. в моем контексте переход [Дата] не является мерой, и использование VAR curDate = LASTDATE(rolling[Date]) (для получения фактического значения строки) дает мне неправильные результаты. Решение @Giovanni Luisotto работает так, как ожидалось.