Allgemeine Joins in RapidMiner
Der letzte Beitrag hat sich mit der Verbesserung von geographischen Joins in RapidMiner beschäftigt. Tatsächlich kann die beschriebene Methode aber auf alle Arten von Joins angewendet werden, die nicht nur für einen kleinen Nutzerkreis interessant sind.
Der eingebaute Join-Operator in RapidMiner erlaubt nur „ist gleich“-Vergleiche. In der Praxis sind aber auch andere Operationen nützlich: z. B. reguläre Ausdrücke, oder „kleiner gleich“.
Der Beispielprozess nutzt generierte Testdaten und wendet eine Liste von regulären Ausdrücken auf sie an. Wie schon bei den geographischen Joins wird dafür ein Scripting-Operator mit einem Groovy-Skript verwendet.
Das Skript muß wie gehabt ziemlich viel Datenverwaltung betreiben, um die resultierende Tabelle aus den beiden Eingangs-Tabelle zu bauen. Bei der Erstellung des Skripts war wichtig, daß es möglichst allgemein verwendbar ist. Das ist in Groovy mit Hilfe der Closure-Syntax möglich: die Join-Funktion wird am Anfang des Skripts als eine Art Konfigurationsvariable festgelegt. Somit sind im Skript nur drei Dinge festzulegen: die beiden Join-Attribute und der Ausdruck, der auf sie anzuwenden ist.
In diesem Beispiel:
es1AttName = "Person"; es2AttName = "regexp"; def joinFunc = { e1, e2 -> e1.matches(e2) }
Die beiden Attributsvariablen aus Example Set 1 und 2 werden am Anfang angegeben. Hier müssen die Attributnamen exakt (inkl. Groß- und Kleinschreibung) angegeben werden.
Die Closure joinFunc nimmt zwei Parameter (e1 und e2) entgegen, das sind die Werte aus den genannten Attributen. Die Funktion prüft in diesem Fall, ob das Person-Attribut dem regulären Ausdruck aus dem zweiten Datensatz entspricht.
Andere Join-Kriterien könnten so lauten:
e1 <= e2 // kleiner-gleich-Vergleich e1 == e2 || e2 == null // Vergleich mit optional fehlenden Daten
usw.
Für den Vergleich mehrerer Variablen muß das Skript dann doch angepaßt werden.
Das Skript verzichtet aus Performance-Gründen auf eine Prüfung, ob gleichnamige Attribute in beiden Datensätzen existieren. Im Zweifelsfall kann die Eindeutigkeit der Namen mit einem Rename by Replacing vor dem Join-Operator sichergestellt werden.
In SQL verwende ich immer wieder komplexe Joins – jetzt wird Ähnliches auch in RapidMiner möglich sein.
Generic Joins in RapidMiner
The last blog entry presented an improvement of geographic joins in RapidMiner. However, the described method can be applied to all kinds of joins, including those usable for a much larger group of analysts.
The Join operator in RapidMiner supports only the „is equal“ comparison. In reality, other operations like regular expression matching or „less or equal“ can be useful.
The example process uses generated data and joins a list of regular expressions with them. A Groovy script in an Execute Script operator is used, just like in the geographic joins.
Much data wrangling is done in the script as usual to build the resulting table from the incoming example sets. I developed the script with the goal of reusability. The closure syntax in Groovy makes this possible: the join function is specified in a kind of configuration variable at the top of the script. So to reuse the script you just need to set three variables: both join attributes and the expression to apply on them.
This is the configuration part in the example script:
es1AttName = "Person"; es2AttName = "regexp"; def joinFunc = { e1, e2 -> e1.matches(e2) }
The attribute variables from ExampleSet 1 and 2 are given in the first two rows. It is important to specify them exactly (including capitalization).
The closure called joinFunc takes two parameters (e1 and e2), the values of the selected attributes. In this case the function executes a regular expression match on them.
Other possible join criteria:
e1 <= e2 // less-or-equal comparison e1 == e2 || e2 == null // comparison that allows missing data
and so on.
The script needs to be changed for joins on multiple variables.
For performance reasons the script doesn‘t check for duplicate attribute names in the incoming data sets. If unsure, just use a Rename by Replace operator before the join to make sure the names are unique.
I‘m using complex joins in SQL all the time – it‘s time to make similar things possible in RapidMiner!