R Data Frames meistern mit dplyr – Teil 2

Dieser Artikel ist Teil 2 von 2 aus der Artikelserie R Data Frames meistern mit dplyr.

Noch mehr Datenbank-Features

Im ersten Teil dieser Artikel-Serie habe ich die Parallelen zwischen Data Frames in R und Relationen in SQL herausgearbeitet und gezeigt, wie das Paket dplyr eine Reihe von SQL-analogen Operationen auf Data Frames standardisiert und optimiert. In diesem Teil möchte ich nun drei weitere Analogien aufzeigen. Es handelt sich um die

  • Window Functions in dplyr als Entsprechung zu analytischen Funktionen in SQL,
  • Joins zwischen Data Frames als Pendant zu Tabellen-Joins
  • Delegation von Data Frame-Operationen zu einer bestehenden SQL-Datenbank

Window Functions

Im letzten Teil habe ich gezeigt, wie durch die Kombination von group_by() und summarise() im Handumdrehen Aggregate entstehen. Das Verb group_by() schafft dabei, wie der Name schon sagt, eine Gruppierung der Zeilen des Data Frame anhand benannter Schlüssel, die oft ordinaler oder kategorialer Natur sind (z.B. Datum, Produkt oder Mitarbeiter).

Ersetzt man die Aggregation mit summarise() durch die Funktion mutate(), um neue Spalten zu bilden, so ist der Effekt des group_by() weiterhin nutzbar, erzeugt aber „Windows“, also Gruppen von Datensätzen des Data Frames mit gleichen Werten der Gruppierungskriterien. Auf diesen Gruppen können nun mittels mutate() beliebige R-Funktionen angewendet werden. Das Ergebnis ist im Gegensatz zu summarise() keine Verdichtung auf einen Datensatz pro Gruppe, sondern eine Erweiterung jeder einzelnen Zeile um neue Werte. Das soll folgendes Beispiel verdeutlichen:

Das group_by() unterteilt den Data Frame nach den 4 gleichen Werten von a. Innerhalb dieser Gruppen berechnen die beispielsweise eingesetzten Funktionen

  • row_number(): Die laufende Nummer in dieser Gruppe
  • n(): Die Gesamtgröße dieser Gruppe
  • n_distinct(b): Die Anzahl verschiedener Werte von b innerhalb der Gruppe
  • rank(desc(b)): Den Rang innerhalb der selben Gruppe, absteigend nach b geordnet
  • lag(b): Den Wert von b der vorherigen Zeile innerhalb derselben Gruppe
  • lead(b): Analog den Wert von b der folgenden Zeile innerhalb derselben Gruppe
  • mean(b): Den Mittelwert von b innerhalb der Gruppe
  • cumsum(b): Die kumulierte Summe der b-Werte innerhalb der Gruppe.

Wichtig ist hierbei, dass die Anwendung dieser Funktionen nicht dazu führt, dass die ursprüngliche Reihenfolge der Datensätze im Data Frame geändert wird. Hier erweist sich ein wesentlicher Unterschied zwischen Data Frames und Datenbank-Relationen von Vorteil: Die Reihenfolge von Datensätzen in Data Frames ist stabil und definiert. Sie resultiert aus der Abfolge der Elemente auf den Vektoren, die die Data Frames bilden. Im Gegensatz dazu haben Tabellen und Views keine Reihenfolge, auf die man sich beim SELECT verlassen kann. Nur mit der ORDER BY-Klausel über eindeutige Schlüsselwerte erreicht man eine definierte, stabile Reihenfolge der resultierenden Datensätze.

Die Wirkungsweise von Window Functions wird noch besser verständlich, wenn in obiger Abfrage das group_by(a) entfernt wird. Dann wirken alle genannten Funktionen auf der einzigen Gruppe, die existiert, nämlich dem gesamten Data Frame:

Anwendbar sind hierbei sämtliche Funktionen, die auf Vektoren wirken. Diese müssen also wie in unserem Beispiel nicht unbedingt aus dplyr stammen. Allerdings komplettiert das Package die Menge der sinnvoll anwendbaren Funktionen um einige wichtige Elemente wie cumany() oder n_distinct().

Data Frames Hand in Hand…

In relationalen Datenbanken wird häufig angestrebt, das Datenmodell zu normalisieren. Dadurch bekommt man die negativen Folgen von Datenredundanz, wie Inkonsistenzen bei Datenmanipulationen und unnötig große Datenvolumina, in den Griff. Dies geschieht unter anderem dadurch, dass tabellarische Datenbestände aufgetrennt werden Stammdaten- und Faktentabellen. Letztere beziehen sich über Fremdschlüsselspalten auf die Primärschlüssel der Stammdatentabellen. Durch Joins, also Abfragen über mehrere Tabellen und Ausnutzen der Fremdschlüsselbeziehungen, werden die normalisierten Tabellen wieder zu einem fachlich kompletten Resultat denormalisiert.

In den Data Frames von R trifft man dieses Modellierungsmuster aus verschiedenen Gründen weit seltener an als in RDBMS. Dennoch gibt es neben der Normalisierung/Denormalisierung andere Fragestellungen, die sich gut durch Joins beantworten lassen. Neben der Zusammenführung von Beobachtungen unterschiedlicher Quellen anhand charakteristischer Schlüssel sind dies bestimmte Mengenoperationen wie Schnitt- und Differenzmengenbildung.

Die traditionelle R-Funktion für den Join zweier Data Frames lautet merge(). dplyr erweitert den Funktionsumfang dieser Funktion und sorgt für sprechendere Funktionsnamen und Konsistenz mit den anderen Operationen.

Hier ein synthetisches Beispiel:

Nun gilt es, die Verkäufe aus dem Data Frame sales mit den Produkten in products zusammenzuführen und auf Basis von Produkten Bilanzen zu erstellen. Diese Denormalisierung geschieht durch das Verb inner_join() auf zweierlei Art und Weise:

Die Ergebnisse sind bis auf die Reihenfolge der Spalten und der Zeilen identisch. Außerdem ist im einen Fall der gemeinsame Schlüssel der Produkt-Id als prod_id, im anderen Fall als id enthalten. dplyr entfernt also die Spalten-Duplikate der Join-Bedingungen. Letzere wird bei Bedarf im by-Argument der Join-Funktion angegeben. R-Experten erkennen hier einen „Named Vector“, also einen Vektor, bei dem jedes Element einen Namen hat. Diese Syntax verwendet dplyr, um elegant die äquivalenten Spalten zu kennzeichnen. Wird das Argument by weggelassen, so verwendet dplyr im Sinne eines „Natural Join“ automatisch alle Spalten, deren Namen in beiden Data Frames vorkommen.

Natürlich können wir dieses Beispiel mit den anderen Verben erweitern, um z.B. eine Umsatzbilanz pro Produkt zu erreichen:

dplyr bringt insgesamt 6 verschiedene Join-Funktionen mit: Neben dem bereits verwendeten Inner Join gibt es die linksseitigen und rechtsseitigen Outer Joins und den Full Join. Diese entsprechen genau der Funktionalität von SQL-Datenbanken. Daneben gibt es die Funktion semi_join(), die in SQL etwa folgendermaßen ausgedrückt würde:

Das Gegenteil, also ein NOT EXISTS, realisiert die sechste Join-Funktion: anti_join(). Im folgenden Beispiel sollen alle Produkte ausgegeben werden, die noch nie verkauft wurden:

… und in der Datenbank

Wir schon mehrfach betont, hat dplyr eine Reihe von Analogien zu SQL-Operationen auf relationalen Datenbanken. R Data Frames entsprechen Tabellen und Views und die dplyr-Operationen den Bausteinen von SELECT-Statements. Daraus ergibt sich die Möglichkeit, dplyr-Funktionen ohne viel Zutun auf eine bestehende Datenbank und deren Relationen zu deligieren.

Mir fallen folgende Szenarien ein, wo dies sinnvoll erscheint:

  • Die zu verarbeitende Datenmenge ist zu groß für das Memory des Rechners, auf dem R läuft.
  • Die interessierenden Daten liegen bereits als Tabellen und Views auf einer Datenbank vor.
  • Die Datenbank hat Features, wie z.B. Parallelverarbeitung oder Bitmap Indexe, die R nicht hat.

In der aktuellen Version 0.5.0 kann dplyr nativ vier Datenbank-Backends ansprechen: SQLite, MySQL, PostgreSQL und Google BigQuery. Ich vermute, unter der Leserschaft des Data Science Blogs dürfte MySQL (oder der Fork MariaDB) die weiteste Verbreitung haben, weshalb ich die folgenden Beispiele darauf zeige. Allerdings muss man beachten, dass MySQL keine Window Funktionen kennt, was sich 1:1 auf die Funktionalität von dplyr auswirkt.

Im folgenden möchte ich zeigen, wie dplyr sich gegen eine bestehende MySQL-Datenbank verbindet und danach einen bestehenden R Data Frame in eine neue Datenbanktabelle wegspeichert:

Die erste Anweisung verbindet R mit einer bestehenden MySQL-Datenbank. Danach lade ich den Data Frame diamonds aus dem Paket ggplot2. Mit str() wird deutlich, dass drei darin enthaltene Variablen vom Typ Factor sind. Damit dplyr damit arbeiten kann, werden sie mit mutate() in Character-Vektoren gewandelt. Dann erzeugt die Funktion copy_to() auf der MySQL-Datenbank eine leere Tabelle namens diamonds, in die die Datensätze kopiert werden. Danach erhält die Tabelle noch drei Indexe (von dem der erste aus drei Segmenten besteht), und zum Schluß führt dplyr noch ein ANALYSE der Tabelle durch, um die Werteverteilungen auf den Spalten für kostenbasierte Optimierung zu bestimmen.

Meistens aber wird bereits eine bestehende Datenbanktabelle die interessierenden Daten enthalten. In diesem Fall lautet die Funktion zum Erstellen des Delegats tbl():

Die Rückgabewerte von copy_to() und von tbl() sind natürlich keine reinrassigen Data Frames, sondern Objekte, auf die die Operationen von dplyr wirken können, indem sie auf die Datenbank deligiert werden. Im folgenden Beispiel sollen alle Diamanten, die ein Gewicht von mindestens 1 Karat haben, pro Cut, Color und Clarity nach Anzahl und mittlerem Preis bilanziert werden:

Die Definition der Variablen bilanz geschieht dabei komplett ohne Interaktion mit der Datenbank. Erst beim Anzeigen von Daten wird das notwendige SQL ermittelt und auf der DB ausgeführt. Die ersten 10 resultierenden Datensätze werden angezeigt. Mittels der mächtigen Funktion explain() erhalten wir das erzeugte SQL-Kommando und sogar den Ausführungsplan auf der Datenbank. SQL-Kundige werden erkennen, dass die verketteten dplyr-Operationen in verschachtelte SELECT-Statements umgesetzt werden.

Zu guter Letzt sollen aber meistens die Ergebnisse der dplyr-Operationen irgendwie gesichert werden. Hier hat der Benutzer die Wahl, ob die Daten auf der Datenbank in einer neuen Tabelle gespeichert werden sollen oder ob sie komplett nach R transferiert werden sollen. Dies erfolgt mit den Funktionen compute() bzw. collect():

Durch diese beiden Operationen wurde eine neue Datenbanktabelle „t_bilanz“ erzeugt und danach der Inhalt der Bilanz als Data Frame zurück in den R-Interpreter geholt. Damit schließt sich der Kreis.

Fazit

Mit dem Paket dplyr von Hadley Wickham wird die Arbeit mit R Data Frames auf eine neue Ebene gehoben. Die Operationen sind konsistent, vollständig und performant. Durch den Verkettungs-Operator %>% erhalten sie auch bei hoher Komplexität eine intuitive Syntax. Viele Aspekte der Funktionalität lehnen sich an Relationale Datenbanken an, sodass Analysten mit SQL-Kenntnissen rasch viele Operationen auf R Data Frames übertragen können.

Zurück zu R Data Frames meistern mit dplyr – Teil 1.

 

Mobilgeräte-Sicherheit

Safety first! Testen Sie Ihr Wissen rund um Mobile Device Management!

Mobile Device Management (MDM) unterstützt nicht nur der Verwaltung von mobilen Endgeräten und die Software- und Datenverteilung. Es ermöglicht vor allem, die nötige Sicherheit, Transparenz und Kontrolle beim Einsatz von Smartphones und Tablets zu schaffen.

Sicherheit ist das A und O bei der unternehmensinternen Nutzung von Mobilgeräten. Neben der klassischen Geräteverwaltung bilden deshalb Security-Funktionen wie Datenverschlüsselung, Remote-Recovery, App Blacklists und ein Malware-Schutz die Hauptpfeiler von MDM-Lösungen.

Zuverlässige Schutzfunktionen sollen vor allem verhindern, dass interne Daten unkontrolliert das Unternehmen verlassen. Zu diesem Zweck sorgt ein MDM-Client auf dem mobilen Device für die Einhaltung der Corporate-Regeln. Solche Regeln könnten beispielsweise die Nutzung von Kamera oder Bluetooth verbieten oder die Installation bestimmter Apps und Browser. Auch Jailbreak und Rooten stehen oft auf der Verbotsliste.

Neben Unterlassungen lassen sich auch Gebote vorschreiben, etwa, dass die Geräte beim Einschalten durch eine PIN-Eingabe entsperrt werden müssen, dass Daten auf den Devices per Backup vor Verlusten geschützt und gestohlene oder verlorene Geräte bereinigt werden müssen.

Solche Policy-Vorgaben werden per Echtzeitüberwachung kontrolliert – gerade beim Arbeiten mit kritischen Datensätzen wie personenbezogenen Daten, Kontodaten und anderen vertraulichen Informationen eine absolute Notwendigkeit. Verstößt ein Nutzer gegen eine oder mehrere dieser Regeln wird der Zugriff auf die geschäftskritischen Ressourcen blockiert. Als letzte Konsequenz und bei Verlust oder Diebstahl kann das Smartphone oder Tablet auch gesperrt oder dessen Inhalte kontrolliert gelöscht werden. Die Lokalisierung, das Sperren und Löschen der mobilen Devices sollte deshalb auch über die Luftschnittstelle möglich sein.

Herausforderung BYOD

Eine weitere Sicherheitshürde ist zu bewältigen, wenn das Unternehmen seinen Mitarbeitern die berufliche Nutzung ihrer privaten Geräte erlaubt: In solchen BYOD-Szenarien (BYOD = Bring Your Own Device) ist die strikte Trennung privater und geschäftlicher Daten ein Muss. Während Unternehmen stets im Auge behalten müssen, welche geschäftskritischen Daten ihre Mitarbeiter erheben, verarbeiten und nutzen, müssen deren private Daten privat bleiben. Hier haben sich Container-Lösungen etabliert. Diese stellen sicher, dass die Anwendungen und ihre Daten in einem abgeschotteten Umfeld (Container) – sauber getrennt voneinander – laufen.

Mit einer Container-Lösung lässt sich beispielsweise verhindern, dass Firmeninformationen per Copy & Paste auf Facebook oder Twitter landen. Ein Zugriff aus dem Firmenkontext auf die private Facebook- oder Twitter-App wäre damit schlichtweg nicht möglich. Durch Container lassen sich somit viele Schwachstellen eliminieren.

Für einen absolut sicheren, rollenbasierten Datenaustausch hochsensibler Dokumente empfiehlt sich die Einrichtung eines Secure Data Rooms. Dieser ist vollständig isoliert und durch multiple Sicherheitsstandards vor unbefugten Zugriffen gesichert. Dem Secure Data Room sind Rollenrechte hinterlegt, so dass nur bestimmte, authentifizierte Nutzergruppen auf diesen Raum zugreifen können. So lässt sich zum Beispiel für die Vorstandsebene ein Secure Data Room anlegen, in dem Geschäftsberichte und Verträge abgelegt und – je nach erlaubten Bearbeitungsstufen – eingesehen oder auch bearbeitet werden können.

In Zusammenarbeit mit IBM

 

Finance Controlling und NoSQL Data Science – zwei Welten treffen aufeinander

Wenn ein konservativer, geschäftskritischer Fachbereich auf neue Technologien mit anderen, kreativen Möglichkeiten trifft, führt das zu Reibungen, aber auch zu Ergebnissen, die andere Personen auf neue Ideen bringen können. Bei dem hier geschilderten Anwendungsfall geht es um die Ermittlung einer kurzfristigen Erfolgrechnung (KER) unter Nutzung von NoSQL-Technologien. Einer Aufgabenstellung, die für beide Seiten sehr lehrreich war.

1-opener-image

Erinnern Sie sich noch an die Werbespots von Apple mit Justin Long und John Hodgman als menschlicher Apple und Personal Computer? Ähnlich wie in den Werbespots sind die beiden Bereiche Finance Controlling und Data Science zu betrachten. Der eine eher konservativ, geschäftskritisch, mit etablierten Methoden und Verfahren; der andere mit einem Zoo voller verschiedener Werkzeuge für den kreativen Umgang mit Daten. Insbesondere wenn dann auch noch NoSQL ins Spiel kommt, mag man glauben, dass keinerlei Berührungspunkte existieren. Dennoch eignen sich neue Technologien auch für etablierte Bereiche und können diese bereichern und auf neue Ideen bringen.

Bei einer kurzfristigen Erfolgsrechnung (sog. KER) handelt es sich um die Aufstellung kaufmännischer Kennzahlen und den Vergleich über Zeiträume. Unter anderem wird hierbei auch häufig von Deckungsbeitragsrechnung oder Betriebsergebnisrechnung gesprochen. Eine KER wird vom Controlling daher aus der kaufmännischen Software generiert (z.B. SAP FiCo) und zumeist nur als Datei oder tatsächlich noch auf Papier an Bereichsleiter oder die Geschäftsführung übergeben.

Ergänzend zu der standardisierten Aufstellung sollte es in dem hier geschilderten Fall möglich sein, dass die Berechnung der KER unter Berücksichtigung von Filtermöglichkeiten ad hoc durch einen Endanwender möglich sein soll. Das bedeutet, dass nicht mehr nur ausschließlich das Controlling die Erfolgsrechnung generieren kann, sondern auch jeder Fachbereich selbständig für sich. Dementsprechend müssen die Werkzeuge aus dem Data Science einmal konfiguriert und benutzerfreundlich bereitgestellt werden.

Die Generierung einer Erfolgrechnung mag auf den ersten Blick nicht direkt als Aufgabe für einen Data Scientist wirken, schließlich sind die Daten und deren Aufbau bekannt, genauso wie die Form des Endergebnisses. Dennoch stellen sich der Vielzahl bekannter Variablen, genauso viele unbekannte gegenüber. Denn wenn ein relationales Modell einfach in eine neue Technologie (NoSQL) überführt wird, hat man nichts dabei gewonnen. Erst der kreative Einsatz neuer Methoden und der etwas andere Umgang mit bekannten Daten führt zu einer Verbesserung und neuen Idee.

Daten

Bei den zu verarbeitenden Daten handelt es sich um Buchungsdaten (SAP Export), Plandaten (csv-Export aus einem Planungssystem) und um manuelle Informationen aus Excel (als csv-Dateien). Insgesamt sind es mindestens neun Datenquellen unterschiedlicher Qualität. Insbesondere bei den manuell erstellten Excel-Daten muss mehrfach geprüft werden, ob die Dateien in dem vereinbarten Format vorliegen. (Gerade bei manuell gepflegten Daten greift Murphys Law – immer!)

Die Inhalte der Excel-Daten reichern die anderen beiden Quelldaten durch weitere Informationen an. Hierbei handelt es sich u.a. um Mappinginformationen zur Ergänzung kurzer Schreibweisen oder maskierter Inhalte, damit diese durch Endanwender gelesen werden können. Beispielsweise sind Kostenstellen in Unternehmensbereiche, Abteilungen und Produktgruppen zu entschlüsseln.

Bei den Buchungsdaten aus dem SAP-System handelt es sich um die monatlichen Saldenwerte eines Kontos, die granular auf Kostenstelle, Marke, Periode und weitere Merkmale heruntergebrochen wurden. Damit wird also nicht pro Monat ein Kontensaldo übergeben, sondern eine Vielzahl von Salden je Konto, je nachdem, wie viele Merkmale geliefert werden.

Beispiel für eine Zeile aus dem SAP-Export:

Je Periode (im Regelfall: Monate) wird eine Datei geliefert; dabei ist aus dem Dateinamen die Betriebszugehörigkeit und die Periode abzulesen. Es gilt zudem, dass ein Unternehmen in mehr als 12 Perioden pro Jahr Buchungen durchführen kann (in diesem Fall bis zu 16).

Die Buchungsinformationen und alle weiteren Dateien werden mit einer Java-Anwendung in die NoSQL-Datenbank importiert. Hierbei wird auf eine multi-model Datenbank zurückgegriffen, um im späteren Verlauf verschiedene NoSQL-Technologien nutzen zu können (z.B. documentstore, graphdb, multi-value und bi-temporal).2-KER-Modell

Modellierung

Für jede Datenquelle wird eine Datensatzart genutzt. Relational gesprochen bedeutet das eine Tabelle je Quelle oder für Benutzer von document stores: eine “collection” für gleichartige Dokumente.

Bei der gewählten Datenbank wird allerdings nicht zwischen verschiedenen “collections” unterschieden. Nur durch ein Feld je Datensatz wird der Typ des Datensatzes festgelegt. In der Anwendung wird dieses Feld interpretiert und der Datensatz entsprechend angezeigt (anhand von Templates für die JSON-Ausgabe). Da – wie bei document stores üblich – die Dokumente ein dynamisches Schema aufweisen, können sich alle Datensätze in ihrer Art und Ausprägung (Key/Values) unterscheiden.

Als Ergänzung zu den bisherigen Quelldaten werden innerhalb der Datenbank weitere Datensätze für das Layout der KER-Ausgabe angelegt. Diese beschreiben im Prinzip nur die Reihenfolge und den Inhalt der späteren Ausgabe (dazu später mehr).

Nach dem Import der Datensätze werden innerhalb der Datenbank zwischen den Datensätzen Verlinkungen (Graphen) etabliert. So zeigen beispielsweise alle Buchungen auf das jeweils betroffene Konto oder eine KER-Ergebniszeile auf eine Kontengruppe. Aus der Skizze zum Datenmodell können die relevanten Verlinkungen abgelesen werden.

Anzumerken ist hier, dass ein Konto in mehreren Kontengruppen auftreten kann. Eine einzelne n:m-Verlinkung wird daher in diesem Fall über separate Datensätze abgehandelt und nicht in einem Datensatz mit einer Unterstruktur. Das wäre zwar auch möglich, erschwert und verlangsamt allerdings etwaige Aktualisierungen, da die csv-Quelle nur eine Zeile je Zuweisung liefert.

Für die Speicherung der Buchungsinformationen wird auf die Funktionalität der bi-temporalen Datenhaltung 3-bitemporalzurückgegriffen. Hierbei erhält jeder Feldinhalt in einem Datensatz (optional) den Vermerk des Gültigkeitszeitpunktes. Neben dem Transaktionszeitpunkt (wann wurden die Daten gespeichert) ist also auch erkennbar ab (oder auch bis) wann ein Inhalt gültig ist. Dabei ist zu beachten, dass “nicht-gültig” etwas anderes ist, als “falsch”. In dieser Art der Verwendung steht “nicht-gültig” für “nicht mehr aktuell” oder auch “noch nicht aktuell”.

Durch diese Art der Datensatzspeicherung reduziert sich die Anzahl der Buchungsdatensätze auf einen Bruchteil des ursprünglichen Datenbestandes. Beispiel: Es werden jeden Monat 10.000 Buchungen geliefert. Für 16 Monate ergeben sich somit 160.000 Datensätze. Da diese bi-temporal gespeichert werden, bleibt es bei 10.000 Datensätzen in der Datenbank mit je max. 16 Gültigkeitswerten je Feld (für jede Periode).

Hier sei noch angemerkt, dass ein Wert so lange gültig ist, bis ein anderer Wert diesen ergänzt. Wird also für Januar ein bestimmter Wert geliefert und im Laufe des Jahres nicht geändert, bleibt dieser bestehen und wird nicht nochmal gespeichert. Statt 16 Einträgen, bleibt es also bei einem.

Ergänzend dazu stellt sich die Frage zum Umgang mit den Perioden 13 bis 16. Da ein Jahr nur 12 Monate besitzt, können diese nicht einfach mit einem falschen Datum gespeichert werden. Hier greift allerdings der Umstand, dass speziell in diesem Anwendungsfall erst am Ende eines Monats durch den Monatsabschluss alle Buchungen korrekt sind. Innerhalb eines Monats ist das nicht der Fall. Es gibt also genau einen (und nur einen) korrekten Zeitpunkt, an dem die Werte korrekt und gültig sind. Die Werte einer Buchung zu diesem Zeitpunkt werden also nur zu einem Tag in dem Datensatz gespeichert.

Schaut man sich nun den Screenshot des Datensatzes mit den Monatswerten an, fällt auf, dass die Salden-Werte (im Feld “SAP-Werte”) jeweils zum Zweiten eines Monats gespeichert wurden. Da es nur einen gültigen Wert je Monat gibt, ist das Datum irrelevant (es hätte auch der Dritte oder Vierte des Monats sein können). Für jede Periode größer 12 wurde einfach vorgesehen, dass diese ab dem 13.12. eines Jahres hinterlegt werden (d.h. für Periode 14 der 14.12.; Periode 15 der 15.12. usw.). Und da zum Anfang eines Jahres alle Buchungen zu bestimmten Konten auf Null gesetzt werden müssen (also zum 01.01.) bietet sich der Zweite eines Monats an.

Nach dem Einlesen aller gelieferten csv-Dateien, erfolgt die Erzeugung von weiteren Datensätzen für das Layout der Ergebnisrechnung. Diese werden einmalig angelegt und können über eine Benutzeroberfläche vom Anwender angepasst werden.

Wie in der Skizze zum Datenmodell zu erkennen, besteht das Layout der KER aus zwei Datensatztypen. Einmal aus der Layout-Definition (nur ein Datensatz) und zum Zweiten aus mehreren Ergebniszeilen, die jeweils über einen Datensatz beschrieben werden.

4-KER-Layout 5-KER-ErgZeile

 

 

 

 

 

 

 

Beide Datensatztypen bestehen dabei fast ausschließlich aus Linkfeldern (Graphen). Das KER-Layout verweist damit auf die beteiligten Zeilen in der Reihenfolge, wie sie später angezeigt werden; ein Datensatz für eine KER-Zeile verweist auf die jeweiligen Kontengruppen.

In einem zusätzlichen Textfeld einer KER-Zeile wird zudem die Formel eingetragen, über die bei der späteren Anzeige ad hoc das Ergebnis der jeweiligen Zeile berechnet wird (in dem abgebildeten, einfachen Fall nur die Summe zweier Kontengruppen). Dazu steht serverseitig die Bibliothek der Google V8 Javascript-Engine zur Verfügung.

Der Screenshot der Ergebniszeile zeigt zudem die Verwendung von “multi-values” in einem Datensatz. Hierbei können verschiedene Inhalte in einem Feld abgelegt und auch mit anderen Feldern kombiniert werden. In diesem Fall gehören jeweils eine Kontengruppe und der prozentuale Bezug zueinander. Andere Anwendungsfälle sind bspw. die Bankverbindungen oder Kontaktdaten einer Person, da diese auch aus mehreren, zusammengehörenden Feldern bestehen und jede Person mehrere besitzen kann.

Bis hierher wurden die Daten importiert, das Datenmodell aufgebaut und die Datensätze miteinander verlinkt. Aus der NoSQL-Trickkiste nutzen wir die bitemporale Datenhaltung, Graphen, multi-values und document stores. Dadurch wird die Anzahl der Datensätze reduziert und das Datenmodell vereinfacht. Im nächsten Schritt geht es darum, die KER-Ausgabe aufzubereiten und die Ergebnisse – unter Berücksichtigung von Filtermöglichkeiten – mit Hilfe von serverseitigem JavaScript zu berechnen.

Anwendung

Der Anwendungsfall KER-Liste ist im Rahmen eines Gesamtprojektes ein Teilaspekt. Daher wurde auf vorhandene Werkzeuge zurückgegriffen, um mit den gegebenen Mitteln den maximalen Nutzen zu erreichen.

Als System steht eine multi-model NoSQL-Platform zur Verfügung, die mehrere Bereiche der NoSQL-Welt abdeckt und nicht nur eine Datenbank beinhaltet, sondern gleich ein ganzes Arsenal an Werkzeugen, um Lösungen zu erschaffen. Dazu gehört unter anderem auch eine standardisierte Webanwendung, in der durch einfache Konfigurationen Anwendungen definiert werden und die es ermöglicht, die serverseitige Bibliothek der Google V8 Javascript-Engine zu nutzen. Dadurch wird ein Großteil des Anwendungsfalles aus der Softwareentwicklung herausgelöst und an den Fachbereich übertragen.

Hierbei ist zu beachten, dass der Data Scientist sich nicht von dem Fachthema vollständig lösen kann. Ein Grundverständnis ist notwendig, um zu verstehen, wie die Problemlage ist und was das Endergebnis sein soll. Genauso muss der Fachbereich Grundlagen des Datenhandlings und des Systems verstehen. Nur beide zusammen können in einer transparenten Kommunikationsstruktur Lösungen erarbeiten.

Nach der Konfiguration des Datenmodells und dem Import der Daten wurde alles Weitere in der Standardanwendung der NoSQL-Plattform umgesetzt. Dieses beinhaltet unter anderem die Konfiguration der Erfolgsrechnung, wie auch den JavaScript-Teil zur Ermittlung der Ergebnisse und später auch die grafische Ausgabe in Form eines Dashboards mit den gleichen Filter-Möglichkeiten der KER-Ausgabe.

Um innerhalb der Anwendung die kurzfristige Erfolgsrechnung zu erzeugen, wird auf die Funktion von Listen zurückgegriffen. Diese können, ausgehend von einem Datensatz, die Graph-Strukturen auflösen und so hierarchische Ausgaben erzeugen. Als Ergänzung dazu ist eine Integration von Javascript innerhalb der Listen möglich, so dass Berechnungen serverseitig durchgeführt und Ergebnisse zur Anzeige gebracht werden können. Darüber hinaus ist die Nutzung über eine HTTP API möglich, um die Anwendung ggf. später durch weitere Funktionen zu erweitern.6-KER-Modell-Hierarchisch

Ausgehend von dem definierten Datensatz für das KER-Layout ermöglicht die Listenfunktionalität die Konfiguration von sog. Sublisten (also Listen in Listen in Listen in …). Hierbei verfolgt die Liste die Graphenstruktur und bringt die jeweiligen Datensätze zur Anzeige. Durch das genutzte Modell ist der Startpunkt somit ein einzelner Datensatz, zu dem dann hierarchisch alle weiteren Datensätze dazu geladen werden.

Die entstehende Baumstrukur ist im ersten Schritt leer und muss im Anschluss durch JavaScript gefüllt werden. Dazu wird einerseits auf die Inhalte aus der untersten Ebene zurückgegriffen, um die Saldenwerte zu lesen; andererseits auch auf die hinterlegten Formeln jeder Ergebniszeile, um mit den Summen der Kontengruppen die Ergebnisse zu ermitteln.

Das Zauberwort bei der Nutzung von Javascript heißt hier “eval”. Durch diese Funktion werden Strings als Script evaluiert. Im Detail werden durch reguläre Ausdrücke die Begriffe in den Formeln (Namen der Kontengruppen) durch die Summenwerte der jeweiligen Kontengruppe ersetzt und danach mit Hilfe von “eval” ausgeführt. Das Ergebnis wird dann an die entsprechende Position in der Liste geschrieben.

Im Weiteren erhalten bestimmte Werte noch unterschiedliche Formate, um den kosmetischen Aspekt zu erfüllen. Am Ende erhält der Anwender eine KER-Liste.

7-ker-Beispiel

Filter

Die Generierung einer vollständigen KER dauert bis zu fünf Sekunden. Dabei liegen bis zu 40.000 Buchungsdatensätze zu Grunde. Durch einen interaktiven Filter kann der Anwender den Umfang der Liste und die Berechnung entsprechend einschränken. Folgende Felder aus den Buchungsdatensätzen stehen dabei für Filterkombinationen zur Verfügung:

  • Buchungskreise (Filialen): 14
  • Geschäftsbereich (Abteilung): 32
  • Kostenstelle: 56
  • Marke: 9
  • Absatzkanal: 12

Hierbei kann der Anwender jede beliebige Kombination in jeder erdenklichen Reihenfolge zur Filterung nutzen. Die Liste wird entsprechend neu berechnet und in unter fünf Sekunden zur Anzeige gebracht (wegen der reduzierten Datenmenge häufig in unter einer Sekunde).

Als Ergänzung zu den Filtermöglichkeiten kann auch der zeitliche Aspekt berücksichtigt werden. Da die Buchungsinformationen bitemporal gespeichert wurden, besteht in der Liste die Möglichkeit, ein beliebiges Datum zu wählen und sich die Werte dazu anzeigen zu lassen.

Gesamtfunktion und Ausblick

Durch den generalistischen Ansatz des Datenmodells und der gewählten Datenbank konnte nicht nur die kurzfristige Erfolgsrechnung in der üblichen, tabellarischen Form ausgegeben werden. Ferner wurde eine grafische Ausgabe mit der Bibliothek d3.js realisiert, so dass jede Führungskraft in der Lage ist, eine ad hoc Analyse durchzuführen. (Ich spreche hier gerne von KRV-tauglich. “Kinder, Rentner, Vorstände”).

Derzeitig wird JavaScript innerhalb von Listen genutzt, um bei Bedarf Werte zu errechnen. Als Ausblick steht hier in Kürze die Möglichkeit zur Verfügung, dass Scripte auch innerhalb von Datensätze abgelegt und autonom von der Datenbank selber ausgeführt werden. Das hat zur Folge, dass Objekte (Datensätze) Algorithmen beinhalten und selbständig Informationen suchen und generieren.

Verwendete NoSQL-Methoden

  • document store
  • GraphDB
  • multi-Value
  • Bitemporal

Erwähnte Technologien, Produkte und Marken in diesem Artikel

Der hier beschriebene Anwendungsfall soll zeigen, dass Data Science nicht nur Endergebnisse liefert, die quasi durch eine “black box” entstanden, dessen Vorgehensweise nur eingeweihte Personen beherrschen und beurteilen können. Es ist vielmehr so, dass die “Wissenschaft” das Wissen dafür schafft, damit ein “normaler” Anwender mit den Daten umgehen kann und einen Mehrwert daraus erhält.