Blog Article & Copyright by Lukas Hillesheim
Reihen wie z.B. Zeitreihen sind nützlich, wenn es darum geht, Vorhersagen zu treffen oder Muster zu erkennen. KQL bietet eine Fülle von Funktionen für die Arbeit mit Reihen an. Der folgende Artikel zeigt, wie die beiden Funktionen make-series und series-fill-linear verwendet werden kann, um fehlende Werte aus den vorhandenen Werten mittels Interpolation zu konstruieren.
Inhalt:
- 1. Szenario
- 2. Vollständiger KQL-Code
- 3. Vollständige Reihe und Visualisierung
- 4. Reihen mit fehlenden Elementen
- 5. Rekonstruktion fehlender Elemente
- 6. Rekonstruktion fehlender Werte
- 7. Darstellung der rekonstruierten Reihe als Linechart
1. Szenario
Dem Artikel liegt folgendes Szenario zu Grunde:
- Schritt 1. Es wird eine Reihe konstruiert, die eine Sinus-Kurve repräsentiert, und der Variablen sinusoid zugewiesen
- Schritt 2. Aus der Reihe sinusoid wird der Bereich 0.5 bis 1 entfernt. Die unvollständige Reihe wird der Variablen missing_range zugewiesen
- Schritt 3. Auf Basis der Reihe missing_range wird eine neue Reihe abgeleitet und der Variablen recomp_xitems zugewiesen. Die Reihe recomp_xitems enthält neue, künstlich berechnete Elemente, die den fehlenden Bereich 0.5 bis 1 ersetzen. Die Elemente stellen die X-Achsen-Elemente der Sinuskurve dar. Die Y-Werte werden für alle neuen Elemente auf -1 gesetzt
- Schritt 4. Auf Basis der Reihe recomp_xitems wird eine neue Reihe abgeleitet und der Variablen recomp_yitems zugewiesen. In dieser Reihe werden für alle X-Elemente mit dem Wert -1 neue - passende - Werte berechnet.
2. Vollständiger KQL Code
Nachfolgend der vollständige Code. Die einzelnen Abschnitte werden später erklärt:
let sinusoid = print x = range(0.01, 5, 0.03) | mv-expand x | serialize | extend row_ix = row_number(1), x = round(todouble(x), 2), y = sin(todouble(x)) | project-reorder row_ix, x, y | sort by row_ix asc; let missing_range = sinusoid | where x < 0.5 or x > 1; let recomp_xitems = missing_range | make-series y = avg (todouble(y)) default = -1 // Set -1 for new items on x from 0.1 to 5 step 0.03; let recomp_yitems = recomp_xitems | extend y = series_fill_linear(y, -1, false); recomp_yitems | mv-expand x, y | serialize | extend row_ix = row_number(1), x = round(todouble(x), 2), y = todouble(y) | render linechart with (xcolumn=x, ycolumns=y)
3. Vollständige Reihe und Visualisierung
Mit dem nachfolgenden KQL-Code wird eine Sinuskurve konstruiert und dargestellt:
- Die Reihe basiert auf einem Decimal-Array im Bereich 0.01 bis 5, das mit der range-Funktion erzeugt wird. Die Schrittweite 0.03 soll dafür sorgen, dass bei der Darstellung keine Artefakte auftreten
- Eine Spalte row_ix mit einer AutoId wird hinzugefügt, um jede Zeile identifizieren und die Daten ggf. sortieren zu können
- Die Daten der Reihe werden der Variablen sinusoid zugewiesen und mit der Funktion render visualisiert
KQL-Code:
let sinusoid = print x = range(0.01, 5, 0.03) | mv-expand x | serialize | extend row_ix = row_number(1), x = round(todouble(x), 2), y = sin(todouble(x)) | project-reorder row_ix, x, y | sort by row_ix asc; sinusoid | render linechart with (xcolumn=x,ycolumns=y)
Output:
4. Reihen mit fehlenden Elementen
Mit dem KQL-Code des Abschnitts 4. wird simuliert, dass es bei der Erhebung von Daten auch zu fehlenden Werten kommen kann. Die in der Variablen sinusoid enthaltene Reihe wird modifiziert, indem die Elemente im Bereich 0.5 bis 1 entfernt werden. Das Ergebnis wird der Variablen missing_range zugewiesen:
KQL-Code:
let missing_range = sinusoid | where x < 0.5 or x > 1; missing_range
Output:
5. Rekonstruktion fehlender Elemente
Ausgehend von einer Reihe mit fehlenden Elementen kann nun die KQL-Funktion make-series diese Elemente rekonstruieren. Im Beispiel erhalten alle neuen Elemente den Wert -1.
KQL-Code:
... let recomp_xitems = missing_range | make-series y = avg (todouble(y)) default = -1 // Set -1 for new items on x from 0.1 to 5 step 0.03; recomp_xitems
Output:
Der Screenshot zeigt, dass die Tupels für X- und Y-Achse in zwei voneinander getrennten Arrays untergebracht sind. Aus den beiden Arrays könnten die Tupels (x,y) gebildet werden, indem beide Arrays gleichzeitig durchlaufen werden. In Python bewerkstelligt dies eine Funktion namens map, in KQL die Funktion mv-expand. Um den Inhalt der Arrays für das Szenario darzustellen und zu zeigen, dass make-series die fehlenden X-Achsen-Elemente tatsächlich künstlich hinzugefügt hat, wird nachfolgend der Inhalt der Variablen recomp_xitems mit Hilfe von mv-expand angezeigt. Die Extraktion ist aber nur aus Gründen der Nachvollziehbarkeit notwendig. Im vollständigen Code-Beispiel von oben fehlt der Zwischenschritt, da die nächste - im Szenario angewandte Funktion - series-fill-linear ist und series-fill-linear die Daten in einem Array-Format erwartet. Es wäre also ein überflüssiger Schritt, die Daten aus den beiden Arrays erst zu entpacken und dann wieder für series-fill-linear zu packen.
Die Ausgabe ist auf X-Werte grösser oder gleich 0.46 eingeschränkt.
Die Ausgabe ist auf X-Werte grösser oder gleich 0.46 eingeschränkt.
KQL-Code:
... let recomp_xitems = missing_range | make-series y = avg (todouble(y)) default = -1 // Set -1 for new items on x from 0.1 to 5 step 0.03; recomp_xitems | mv-expand x, y | extend x = round(todouble(x), 2) | project-reorder x, y | where x >= 0.46 | sort by x asc
Output:
6. Rekonstruktion fehlender Werte
Im letzten Schritt wird die Funktion series-fill-linear verwendet, um die Dummy-Werte -1 durch solche neuen Werte zu ersetzen, die zu den vorhandenen Reihen-Werten passen.
KQL-Code:
... let recomp_yitems = recomp_xitems | extend y = series_fill_linear(y, -1, false); recomp_yitems
Output:
Wie in 5. Rekonstruktion fehlender Elemente auch, wird der Inhalt der Arrays entpackt, um die neu zugewiesenen Werte anzuzeigen:
KQL-Code:
... let recomp_yitems = recomp_xitems | extend y = series_fill_linear(y, -1, false); recomp_yitems | mv-expand x, y | extend x = round(todouble(x), 2) | project-reorder x, y | where x >= 0.46 | sort by x asc
Output:
7. Darstellung der rekonstruierten Reihe als Linechart
Rekonstruierte Reihe als Linechart dargestellt.
KQL-Code:
... recomp_yitems | mv-expand x, y | serialize | extend row_ix = row_number(1), x = round(todouble(x), 2), y = todouble(y) | render linechart with (xcolumn=x, ycolumns=y)
Output:
Der rekonstruierte Bereich 0.5 bis 1 ist nicht so glatt wie der restliche Bereich. Durch Anwendung weiterer Verfahren könnte dies wegoptimiert werden.