Не прекращайте учебу с
LOKAD TV
read "/sample/Lokad_Items.tsv" read "/sample/Lokad_Orders.tsv" as O read "/sample/Lokad_PurchaseOrders.tsv" as PO show label "Time-series calculations" a1f1 tomato end := max(date) lastMon := monday(end) Week.sold := sum(O.NetAmount) when date >= end - 52 * 7 show linechart "Weekly sales" a2f4 tomato unit:"$" with Week.sold as "This year" Week.sold[-52] as "Last year" Week.ma := sum(O.NetAmount / 4) over [-3 .. 0] when date >= end - 52 * 7 show linechart "Weekly sales with 4 weeks moving average" a5f7 tomato unit:"$" with Week.ma as "This year" Week.ma[-52] as "Last year" Day.cashFlow := sum(O.NetAmount) - sum(PO.NetAmount) Day.balance := avg(Day.cashFlow) over [-13 .. 0] when date >= lastMon - 6 * 7 & date < lastMon show linechart "Cash flow over the last 6 weeks" a8f10 tomato unit:"$" with Day.balance as "Balance" PO.Price = PO.NetAmount / PO.Quantity O.PurchasePrice = latest(PO.Price) O.Cost = O.PurchasePrice * O.Quantity O.Profit = O.NetAmount - O.Cost Week.profitblty := sum(O.Profit) / sum(O.Cost) or 1 when date >= lastMon - 13 * 7 & date < lastMon show linechart "Profitability over the last 13 weeks" a11f13 tomato unit:"%" with Week.profitbltyПосле выполнения данного сценария с использованием образца набора данных будет создана следующая панель управления.
Day
, Week
и Month
соответственно. Эти таблицы называются «виртуальными», потому что они не представлены в виде табличных файлов. Другими словами, эти таблицы существуют только во время выполнения сценария. Сценарий выше использует эти три таблицы для отображения линейных графиков. Взглянем еще раз на соответствующие строки кода.
Week.sold := sum(O.NetAmount) end := max(date) when date >= end - 52 * 7 show linechart "Weekly sales" a2f4 tomato unit:"$" with Week.sold as "This year" Week.sold[-52] as "Last year"В строке 1 содержимое таблицы
O
суммируется и представляется в виде таблицы Week
. В данном сценарии мы используем операцию скалярного присваивания :=
, поэтому за каждую неделю здесь высчитывается единственное значение. В строке 3 задается фильтр, который исключает данные, возраст которых превышает 52 недели. Наконец, в строках 4–6 задается линейный график, отражающий два временных ряда. Второй временной ряд Week.sold[-52]
имеет оператор отставания, который мы рассмотрим в следующем разделе.
Этот сценарий можно легко изменить, используя ежедневное или ежемесячное объединение данных. Например, можно добавить следующие строки в самом конце сценария:
Day.sold := sum(O.NetAmount) show linechart "Daily sales" a14f16 tomato unit:"$" with Day.sold Month.sold := sum(O.NetAmount) show linechart "Monthly sales" a17f19 tomato unit:"$" with Month.soldДанный сегмент кода содержит еще два линейных графика, при этом временные ряды объединяются в них ежедневно и ежемесячно соответственно. Переменная
Day.sold
может пониматься как содержимое столбца sold
в таблице Day
, но ее также можно понять как равномерный временной ряд с периодом в 1 день в отличие от обычных таблиц Envision, которые содержат колонку Date
(например таблица O
) и которые можно понимать как неравномерные временные ряды.Week.sold := sum(O.NetAmount) when date >= end - 52 * 7 show linechart "Weekly sales" a2f4 tomato unit:"$" with Week.sold as "This year" Week.sold[-52] as "Last year"В строках 4 и 5 задаются два временных ряда. Первый временной ряд
Week.sold
представляет собой данные о продажах, объединенные по неделям. Второй временной ряд имеет дополнительный суффикс [-52]
. Этот суффикс сам по себе является оператором отставания. Это означает, что данные, возраст которых превышает 52 недели, перемещаются вперед по временному ряду и отображаются в линейном графике. Когда оператор отставания применяется к таблице Week
, аргумент отставания представляет собой целое число, выражающее количество недель. Точно так же, для таблиц Day
и Month
используются дни и месяцы соответственно.when
. На самом деле, без такого активного взаимодействия фильтр when
исключил бы все данные, возраст которых превышает 52 недели, и выполнение операции отставания временного ряда на 52 недели привело бы к отображению нулевых значений. Как видно на изображении панели управления, рассмотренной ранее, оператор отставания правильно перемещает значения за предыдущий год вперед, потому что они не все равны нулю. Это достигается за счет взаимодействия между фильтром when
и оператором отставания.Week.lastYear
.
Week.sold := sum(O.NetAmount) Week.lastYear := Week.sold[-52] when date >= end - 52 * 7 show linechart "Weekly sales" a2f4 tomato unit:"$" with Week.sold as "This year" Week.lastYear as "Last year"//проблемы отображения датыЕсли запустить измененный сценарий и навести мышь на определенные места во временных рядах, вы заметите, что даты в обоих временных рядах совпадают. В данном случае код, отвечающий за отображение дат, невозможно интерпретировать двояко. Например, временной ряд
Week.lastYear
на самом деле можно интерпретировать как ежегодный прогноз, а в этом случае нам нужно было получить одни и те же даты для двух временных рядов. В заключение, если вы хотите сохранить исходные даты в своем линейном графике для сравнения отстающих временных рядов, то оператор отставания должен быть задан в пределах оператора show
.Week.ma := sum(O.NetAmount / 4) over [-3 .. 0] when date >= end - 52 * 7 show linechart "Weekly sales with 4 weeks moving average" a5f7 tomato unit:"$" with Week.ma as "This year" Week.ma[-52] as "Last year"В строке 1 объединение выполняется с помощью агрегатора
sum()
, и это объединение содержит оператор, который начинается с ключевого слова over
в конце сегмента. В строке 2 применяется фильтр, отсекающий данные, которым больше 52 недель. Наконец, в строках с 3 по 5 задано два временных ряда, которые отображаются в линейном графике. Оба временных ряда «сглаживаются» по мере расчета средних значений за 4 недели.over
используется для определения соответствующего временного интервала, и он должен быть записан следующим образом: [a .. b]
, где a
и b
представляют собой целые числа, причем a
должно быть меньше или равно b
. Единицы, используемые в a
и b
, зависят от выражения слева от операции присваивания. В данном случае у нас есть таблица Week
слева от операции присваивания и в результате -3
и 0
выражаются в неделях. over
можно использовать со всеми агрегаторами. При использовании данного параметра выражение слева от оператора присваивания обычно представляет собой виртуальный календарь с таблицей Day
, Week
или Month
. Это не обязательное требование, и использовать можно любую таблицу, если в ней есть колонка Date
. Кроме того, при использовании таблиц календарей структура over [0 .. 0]
дает те же результаты, что и объединение по умолчанию:
Week.sold := sum(O.NetAmount) // тот же результат! Week.same := sum(O.NetAmount) over [0 .. 0]
Day.cashFlow := sum(O.NetAmount) - sum(PO.NetAmount) Day.balance := avg(Day.cashFlow) over [-13 .. 0] when date >= monday(end) - 42 & date < monday(end) show linechart "Cash flow over the last 6 weeks" a8f10 tomato unit:"$" with Day.balance as "Balance"В строке 1 временной ряд
Day.cashFlow
задан как разность общей суммы продаж и общей суммы закупок. В строке 2 рассчитывается временной ряд Day.balance
, который представлен как скользящее среднее значение Day.cashFlow
за 14 дней. В строке 3 задается фильтр с двумя специфическими условиями: данные должны быть не старее 7 недель, считая с прошлого понедельника, и данные должны быть не «моложе» прошлого понедельника. Функция monday()
, используемая здесь, отвечает за то, чтобы рассматриваемый период времени составлял ровно 6 целых недель. Наконец, в линейном графике, заданном в строках 4 и 5, отображается только временной ряд Day.balance
.over
, который мы описали в предыдущем разделе. Здесь рассчитывается среднее значение для временного ряда за 14 дней. И действительно, между показателями -13 и 0 насчитывается 14 значений. Это объединение не похоже на объединения, которые мы рассматривали ранее, потому что таблица Day
появилась слева и справа от операции присваивания, тогда как обычно при объединении, когда не используется суффикс over
, данные из одной таблицы преобразуются в другую таблицу.Day.cashFlow := sum(O.NetAmount) - sum(PO.NetAmount) Week.balance := sum(Day.cashFlow / 2) over [-1 .. 0] when date >= monday(end) - 42 & date < monday(end) show linechart "Cash flow over the last 6 weeks" a8f10 tomato unit:"$" with Week.balance as "Balance"
PO.Price = PO.NetAmount / PO.Quantity O.PurchasePrice = latest(PO.Price) O.Cost = O.PurchasePrice * O.Quantity O.Profit = O.NetAmount - O.Cost Week.profitblty := sum(O.Profit) / sum(O.Cost) or 1 when date >= lastMon - 13 * 7 & date < lastMon show linechart "Profitability over the last 13 weeks" a11f13 tomato unit:"%" with Week.profitbltyВ строке 1 закупочная цена за единицу рассчитывается в каждой строке таблицы
PO
с помощью обычных векторных операций Envision. В строке 2 используется функция latest
, и она работает очень специфическим образом: для каждой строки таблицы O
(таблицы, к которой она применяется) функция latest
ищет самую новую строку PO.Price
из имеющихся, не новее, чем указанная строка таблицы O
, и копирует данное значение слева от операции присваивания. В строках 3 и 4 прописаны дальнейшие расчеты с использованием векторов и объединения. Наконец, в строке 5 задан фильтр ограничения операций периодом в 13 целых недель. В блоке этого фильтра прописан линейный график, включающий в себя временной ряд Week.profitability
, который был ранее рассчитан в строке 4.latest
поддерживает расчеты, рассматриваемые в настоящем документе. Данная функция предназначена для работы с событиями, когда одно значение считается постоянным до тех пор, пока оно не будет изменено на новое. В частности, можно «уплотнить» закупочные цены, рассчитывая цену за каждый день истории данных с помощью следующего алгоритма:
Day.PurchasePrice = latest(PO.Price)На практике функция
latest
может быть использована для работы со многими ситуациями, такими как дефицит товаров, промоакции, жизненный цикл продукции и т. д.