Berechnung von Zeitreihen mit Envision - Software zur Bestandsoptimierung

Berechnung von Zeitreihen mit Envision












Startseite » Ressourcen » Hier

Die meisten Unternehmensvorgänge in jedem Betrieb können mit Zeitreihen genau dargestellt werden: Verkaufshistorie, Einkaufshistorie, historische Preise, usw. Da die Arbeit mit Zeitreihen für Unternehmen vorrangig ist, bietet Envision eine breite native Unterstützung für diese Art von Szenarien. Insbesondere ist es bei Envision möglich, Daten täglich, wöchentlich und monatlich zu aggregieren. Zusätzlich können auch komplexere Zeitreihenanalysen ausgeführt werden, wie verzögerte Indikatoren, oder die Berechnung von gleitenden Mittelpunktwerten. Diese Features werden auf dieser Seite vorgestellt und dokumentiert.

Ein veranschaulichendes Beispiel

Wir benutzen wieder unser Beispiel-Dataset, um die Fähigkeiten von Envision zu zeigen. Da dieser Abschnitt eine etwas komplexere Nutzung von Envision darstellt, empfehlen wir Ihnen, bevor Sie mit diesen Inhalten arbeiten, Berechnungen erstellen und Aggregation von Daten zu lesen.

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
Nachdem Sie dieses Skript mit dem Beispiel-Dataset ausführen, erhalten Sie folgendes Dashboard.

Image

Virtuelle Kalendertabellen

Da tägliche, wöchentliche und monatliche Aggregationen universell sind, wurde bei der Entwicklung von Envision auf eine native Unterstützung dieser periodischen Kalendermuster geachtet. Konkreter profitieren Sie mit Envision von drei virtuellen Tabellen namens Day, Week und Month. Diese Tabellen werden als „virtuell“ bezeichnet, weil sie keinen entsprechenden tabellarischen Dateien zugeordnet sind. Anders gesagt, existieren diese Tabellen nur während der Ausführung des Skripts. Das obere Skript nutzt diese virtuellen Tabellen, um Liniendiagramme anzuzeigen. Sehen wir uns die relevanten Zeilen, die unten kopiert sind, genauer an.
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"
In Zeile 1 wird der Inhalt der O Tabelle in die Week Tabelle addiert. Da hier die skalare Zuordnung := benutzt wird, wird ein einzelner Wert pro Woche berechnet. In Zeile 3 wird ein Filter definiert, um die Daten, die über 52 Wochen alt sind, auszuschließen. Zuletzt wird in Zeilen 4 bis 6 wird ein angezeigtes Liniendiagramm mit zwei Zeitreihen definiert. Die zweite Zeitreihe {{Week.sold[-52]}} kommt mit einem Verzögerungsoperator, der im nächsten Abschnitt erläutert wird. Dieses Skript kann einfach auf eine tägliche oder monatliche Aggregation abgeändert werden. Beispielsweise ist es möglich, folgende Zeilen am Ende des Skripts hinzuzufügen:
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
Dieser Code-Block zeigt zwei weitere Liniendiagramme an, die täglich und monatlich aggregierte Zeitreihen darstellen. Die Variable Day.sold kann als der Inhalt der Spalte namens sold in der Day Tabelle interpretiert werden, doch sie kann auch als eine gleichmäßig verteilte Zeitreihe des „1-tägigen“ Zeitraums, im Vergleich zu den gewöhnlichen Tabellen in Envision, die eine Date Spalte, wie O enthalten, und als ungleichmäßig verteilte Zeitreihen verstanden werden, interpretiert werden.

Verzögerte Zeitreihen anzeigen

In der Zeitreihenanalyse bezieht sich das „lagging“ (die Verzögerung) auf eine Operation, in der die Elemente der Zeitreihe zeitlich verschoben werden. Eines der Grundziele der zeitlichen Verzögerung ist der Vergleich von zwei verschiedenen Zeitabschnitten. Envision unterstützt einen lag operator (Verzögerungsoperator), der genau auf solche Fälle ausgerichtet ist. Sehen wir uns den vorangehenden Code-Snippet etwas genauer an.
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"
In Zeilen 4 und 5 werden zwei Zeitreihen definiert. Die erste Zeitreihe, Week.sold, stellt die ursprünglichen wöchentlich aggregierten Umsätze dar. Die zweite Reihe hat ein zusätzliches Suffix [-52]. Dieses Suffix ist der tatsächliche Verzögerungsoperator. Dadurch werden die Daten, die den letzten 52 Wochen entsprechen, weitergereicht und letzten Endes auch im Liniendiagramm angezeigt. Wird der Verzögerungsoperator auf die Week Tabelle angewandt, ist dieser ein Integer, der in wöchentlichen Einheiten ausgedrückt wird. Ähnlich werden die anwendbaren Einheiten zu Tagen oder Monaten bei den Tabellen Day und Month.

Der Verzögerungsoperator profitiert von dem schlauen und kooperativen Verhalten des Filteroperators when. Denn ohne dieses Verhalten würde der whenn Filter die Daten, die älter als 52 waren, ausschließen, und die Verzögerung der Zeitreihen von 52 Wochen hätte nur Nullen weitergegeben. Doch, wie man am vorangehenden Screenshot des Dashboards erkennen kann, reicht der Verzögerungsoperator die tatsächlichen Daten, die 1 Jahr alt sind, und keine Nullen weiter. Dieses Verhalten ist dank einer eingebetteten Kooperation zwischen dem when Filter und dem Verzögerungsoperator möglich.

Außerdem können Sie bemerken, dass das Datum und die Werten angezeigt werden, wenn Sie mit der Maus über die Linien in Ihrem Dashboard fahren. Mit dem ersten Skript in diesem Abschnitt, unterscheiden sich die Daten der Zeitreihe “Last year” genau um ein Jahr von denen der Zeitreihe “This year”. Dennoch sollte einem bewusst sein, dass der Verzögerungsoperator in Wirklichkeit nicht das originale Datum der Zeitreihe behält. Stattdessen benutzt Envision einfach eine Konvention, damit dies funktioniert: Wird der Verzögerungsoperator innerhalb der Deklaration eines Liniendiagramms definiert, bleibt ausschließlich in diesem Fall das originale Datum erhalten.

Wir ändern nun das Skript, um den Verzögerungsoperator außerhalb des Liniendiagramms anzuwenden. Dies kann durch das Einführen der Variable Week.lastYear vorgenommen werden.
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"//date display issue
Wenn Sie nun dieses veränderte Skript ausführen und mit Ihrer Maus über die Punkte der Zeitreihen fahren, sollten Sie sehen, dass in beiden Zeitreihen mit dasselbe Datum angegeben wird. In diesem Fall besteht tatsächlich keine eindeutige Semantik für die Anzeige des Datums. So könnte die Zeitreihe Week.lastYear als jährliche Prognose interpretiert werden. Dasselbe Datum in beiden Zeitreihen zu erhalten, wäre das eigentliche Ergebnis in diesem Fall gewesen. Sollten Sie also das originale Datum in Ihrem Liniendiagramm für einen Vergleich der verzögerten Zeitreihen erhalten wollen, sollte der Verzögerungsoperator in der show Anweisung definiert werden.

Aggregierung von Daten über ein Zeitabschnitte

In einer unserer früheren Bedienungsanleitungen haben wir bereits erklärt, wie man in Envision Daten aggregiert. Bei Zeitreihen ist oft eine andere Art von Aggregation erwünscht: die Aggregation über einen Zeitabschnitt. Im ersten Skript dieses Abschnitts, können Sie sehen, wie man den gleitenden Mittelwert der Umsätze der letzten 4 Wochen berechnen kann. Zur Erläuterung werden die relevanten Zeilen hierunter kopiert.

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"
In Zeile 1 wird eine Aggregation mit dem Aggregator sum() vorgenommen. Diese Aggregation kommt mit einer Anweisung, die am Ende mit dem Schlüsselwort over beginnt. In Zeile 2 werden die Daten gefiltert, indem die Daten der letzten 52 Wochen behalten werden. Zuletzt werden in Zeile 3 bis 5 die zwei Zeitreihen im Liniendiagramm angezeigt. Beide Zeitreihen sind „geglättet“, da Durchschnitte über 4 Wochen berechnet werden.

Der Operator over wird benutzt, um die anwendbaren Zeitabschnitte zu definieren und sollte, wie folgt, geschrieben werden: [a .. b], wobei a und b Integer sind und a kleiner oder gleich b ist. Die Einheit, die für a und b genutzt wird hängt von dem Ausdruck auf der linken Seite der Zuordnung ab. In diesem Falle haben wir auf der linken Seite der Zuordnung die Week Tabelle und folglich werden -3 und 0 in Wochen ausgedrückt.

Hinweis: Zwischen der Indexwoche -3 und der Indexwoche 0 gibt es 4 Wochen, nicht 3. Daher bestehen folgende Indexwochen -3, -2, -1 und 0.
Die Option over kann mit allen Aggregatoren genutzt werden. Wird diese Option genutzt, ist die linke Seite der Zuordnung normalerweise eine virtuelle Kalendertabelle, wie Day, Week oder Month. Dennoch ist dies nicht erforderlich und es kann jede Tabelle genutzt werden, solange sie mit einem Date indexiert ist. Per Definition erhält man dasselbe Ergebnis bei der Nutzung von over [0 .. 0], wenn Kalendertabellen genutzt werden, wie bei Standardaggregationen:
Week.sold := sum(O.NetAmount)
// same result!
Week.same := sum(O.NetAmount) over [0 .. 0]

Komplexere Aggregationen von Zeitreihen

Envisions Syntax bietet die Möglichkeit, aufwändigere Berechnungen mit Zeitreihen auszuführen. So ist es beispielsweise möglich, Zeitreihen zu berechnen und weitere Berechnungen auf Grundlage dieser ursprünglichen Zeitreihen vorzunehmen. Am dritten Code-Block des oberen Skripts am Anfang dieser Seite können Sie dies sehen. Die relevanten Zeilen werden hierunter kopiert.
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"
In Zeilen 1 wird die Zeitreihe Day.cashFlow als Differenz zwischen den Gesamtumsätze und den Gesamtkäufen definiert. In Zeile 2 wird die Zeitreihe Day.balance als gleitender Mittelwert von 14 Tagen der Differenz zwischen Day.cashFlow berechnet. In Zeile 3 wird ein Filter mit zwei spezifischen Bedingungen definiert: Daten sollten nicht über 7 Wochen alt sein, ausgehend vom letzten Montag, und sie sollten auch nicht nach dem letzten Montag entstanden sein. Die Funktion monday() versichert dabei, dass das Ziel 6 ganze Wochen beinhaltet. Zuletzt wird die Zeitreihe Day.balance als einzige Zeitreihe im Liniendiagramm angezeigt, die in in Zeilen 4 und 5 definiert ist.

Die Aggregation in Zeile 2 nutzt die Option over, die wir im vorangehenden Abschnitt erläutert haben. Hier wird der Durchschnitt der Zeitreihe über einen Zeitabschnitt von 14 Tagen berechnet, so bestehen zwischen dem Index -13 und 0 14 verschiedene Indizes. Diese Aggregation kommt seltener als andere, die wir schon gesehen haben, vor, da auf beiden Seiten der Zuordnung, rechts und links, die Tabelle Day} erscheint. Gewöhnliche Aggregationen ohne over Suffix aggregieren normalerweise Daten aus einer Tabelle in eine andere.

Es ist auch möglich, tägliche Zeitreihen in wöchentliche Zeitreihen zu aggregieren. Im unteren Skript können Sie sehen, wie wöchentliche Cash-Flows statt Täglichen berechnet werden können.
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"

Umgang mit ereignisbezogenen Daten

Ereignisbezogene Daten sind bestimmte Darstellungen von historischen Daten, die sich auf „Veränderungen“ konzentrieren. Zum Beispiel ist es praktischer, anstatt die historischen Daten der Preise täglich anzugeben, nur die historischen Preisveränderungen zu nutzen. Jede Preisveränderung ergibt einen neuen Preis und ein neues Datum und man geht davon aus, dass der Preis gleich bleibt, bis eine neue Preisveränderung beobachtet wird. Envision unterstützt Szenarien, in denen historische Daten als eine Liste von Veränderungen dargestellt werden.

Das Beispiel-Dataset beinhaltet keine Tabelle mit historischen Preisen, doch es ist möglich, ähnliche Daten zu erhalten, wenn man die vergangenen Einkaufstransaktionen betrachtet und davon ausgeht, dass Preise bis zur nächsten Transaktion gleich bleiben. Genau dies ist, was im letzten Block des Skripts im Beispiel am Anfang dieses Abschnitts zu sehen ist. Sehen wir uns die unten kopierten relevanten Zeilen etwas genauer an.
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
In Zeile 1 wird mittels einer Vektorberechnung der Einkaufspreis pro Einheit für jede Zeile der PO Tabelle im üblichen Stil von Envision berechnet. In Zeile 2 wird die latest Funktion benutzt, die ein ziemlich spezifisches Verhalten hat: für jede Zeile der O Tabelle, die Tabelle der etwa zugeordnet wird, schlägt die latest Funktion die neueste verfügbare PO.Price Zeile nach, die nicht jünger als die O Zeile, um die es geht, sein darf und kopiert diesen Wert auf die linke Seite der Zuordnung. In Zeilen 3 und 4 tauchen weitere Berechnungen mit Vektoren und Aggregationen auf. Zuletzt wird in Zeile 5 ein Filter definiert, um das Ziel der Berechnungen auf die letzten ganzen 13 Wochen zu beschränken. In diesem Filter-Block wird ein Liniendiagramm angezeigt, das die in Zeile 4 zuvor erstellte Week.profitability Zeitreihe nutzt.

Konkret ermöglicht die latest Funktion die hier erwünschte Berechnung. Diese Funktion ist genau dafür ausgelegt, die Semantik einer Folge von Ereignissen, bei denen davon ausgegangen wird, dass ein Wert konstant ist, bis es durch ein neues Ereignis überschrieben wird. Genauer, ist es auch möglich, die Einkaufspreise zu „verdichten“, indem ein Preis für jeden einzelnen Tag des historischen Zeitraums mit folgenden Angaben berechnet wird:
Day.PurchasePrice = latest(PO.Price)
In der Praxis kann die latest Funktion in vielen Fällen genutzt werden, wie etwa bei Fehlbeständen, Aktionen, Lebenszyklen von Produkten, usw.