#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 работает так, как ожидалось.