GIS in RapidMiner (2) – Shapefile import

(English version)

Update 2020-02: GIS-Funktionalität ist jetzt als Erweiterung verfügbar.

Nach der Einführung und Installation geht es um eine konkrete Aufgabenstellung: den Import von Shapefiles.

Shapefile ist ein etabliertes Dateiformat, das zusätzlich zu den Geodaten auch eine Liste von Attributen der abgebildeten Objekte enthalten kann. Die geographischen Objekte können vom Typ Punkt (Point), Linie (LineString) und Polygon sein, jeweils als einzelne oder als Multi-Objekte (MultiPoint usw.).

Meistens bekommt man Shapefile in Form von Zip-Archiven, die die Shape-Datei selbst (*.shp), die Attributdatebank (*.dbf), die Information zur verwendeten Projektion (*.prj) und weitere enthalten.

Wer keine Shape-Datei zur Verfügung hat, findet z. B. bei Geofabrik oder auf Open-Data-Sites (AT, US) welche.

Der RapidMiner-Prozess fürs Einlesen der entpackten Datei ist gleichzeitig eine gute Einführung in die Datenstrukturen von RapidMiner.

Der Prozess steht hier zum Download bereit. Da der Dateiname als Makro im Prozesskontext (View/Show View/Context) definiert wird, steht dieser Prozess als fertiges „Element” zum Einbinden in eigene Prozesse zur Verfügung; der Filename-Parameter wird im aufrufenden Prozess unter „macros” eingetragen.

Nach dem Einlesen der Shape-Datei werden die Metadaten abgefragt (Layer.schema.fields), danach werden die einzelnen Elemente (Features in der GIS-Terminologie) gelesen:

def shp = new Shapefile("%{FILENAME}")
int fields = shp.schema.fields.size();
...
shp.schema.fields.each{f ->
  ...
  fieldMeta[fld] = f;
}
...
shp.features.each { f ->
  data = new Object[fields];
  fieldMeta.each{ attr ->
    data[fld] = f.get(attr.name).toString();
  }
  fld++;
}

Der RapidMiner-spezifische Teil erzeugt zuerst ein Array mit den Attributen, deren Namen und Datentypen aus den Fields des Shapefile-Schemas aufgebaut werden. Mit dem Attribut-Array wird dann ein ExampleTable erzeugt. Nach dem schrittweise  Befüllen des data-Arrays wird jedes Example mit einem DataRowFactory erzeugt und ans ExampleTable angefügt. Dieses wird am Ende in ein ExampleSet umgewandelt und als erster Output ausgegeben.

Attribute[] attributes= new Attribute[fields];

shp.schema.fields.each{f ->
 if (f.typ == "Long" || f.typ == "Integer") {
 attributes[fld] = AttributeFactory.createAttribute(f.name, Ontology.INTEGER);
 ...
}

MemoryExampleTable table = new MemoryExampleTable(attributes);

DataRowFactory ROW_FACTORY = new DataRowFactory(0);
...
shp.features.each { f ->
 data = new Object[fields];
 fld = 0;
 fieldMeta.each{ attr ->
  if (attr.typ == "Long" || attr.typ == "Integer" || attr.typ == "Double" || attr.typ == "Single") {
   data[fld] = f.get(attr.name);
  } else {
   data[fld] = f.get(attr.name).toString();
  }
  fld++;
 }
 DataRow row = ROW_FACTORY.create(data, attributes);
 table.addDataRow(row);
}

ExampleSet exampleSet = table.createExampleSet();
return exampleSet;

Das Ergebnis des Skript-Aufrufs ist ein normales RapidMiner-ExampleSet, dessen Metadaten aus dem Shapefile stammen. Numerische Attribute sind entsprechend konvertiert, sodaß der Datensatz ganz normal weiterverwendet werden kann. Handelt es sich um eine Geometrie aus Punkten, kann man sogar leicht die X- und Y-Koordinaten extrahieren und den Datensatz darstellen (in diesem Beispiel Orte in Ungarn):

Orte in Ungarn
Orte in Ungarn. Shapefile von Geofabrik in RapidMiner importiert.
Daten: © OpenStreetMap Contributors

Shapefile Import into RapidMiner

Update 2020-02: GIS functionality is now available in an extension.

After the introduction and installation we can start to work on an actual task: importing shapefiles.

Shapefile is a popular file format that is able to store geospatial data with additional attributes of each object. Points, LineStrings, Polygons and their Multi-versions (e. g. MultiPoint) are supported.

Usually a “shapefile” is a Zip archive that contains the shape file itself (*.shp), the database of attributes (*.dbf), the projection information (*.prj) and more.

If you don’t have a shapefile for testing yet, you can find some at Geofabrik and on Open Data sites (AT, US).

The RapidMiner process that reads the unpacked file is also a good introduction into the data structures of RapidMiner.

The process is available for download here. The file name is defined in the process context as a macro (View/Show View/Context), so you can use this process as a ready-to-use element in your own processes. Just include the file name to import in the macros entry of the Execute Process operator.

After reading the shapefile, the script determines the metadata of the fields (Layer.schema.fields) and reads the elements (called feature in GIS software).

def shp = new Shapefile("%{FILENAME}")
int fields = shp.schema.fields.size();
...
shp.schema.fields.each{f ->
  ...
  fieldMeta[fld] = f;
}
...
shp.features.each { f ->
  data = new Object[fields];
  fieldMeta.each{ attr ->
    data[fld] = f.get(attr.name).toString();
  }
  fld++;
}

The RapidMiner specific part creates an array for the attributes and reads their names and data types from the Fields of the shapefile Schema. An ExampleTable is created from the attribute array. After filling a data array step by step, it is converted to a data row using a DataRowFactory and appended to the ExampleTable. This table is converted to an ExampleSet and returned as the first output of the operator.

Attribute[] attributes= new Attribute[fields];

shp.schema.fields.each{f ->
 if (f.typ == "Long" || f.typ == "Integer") {
 attributes[fld] = AttributeFactory.createAttribute(f.name, Ontology.INTEGER);
 ...
}

MemoryExampleTable table = new MemoryExampleTable(attributes);

DataRowFactory ROW_FACTORY = new DataRowFactory(0);
...
shp.features.each { f ->
 data = new Object[fields];
 fld = 0;
 fieldMeta.each{ attr ->
  if (attr.typ == "Long" || attr.typ == "Integer" || attr.typ == "Double" || attr.typ == "Single") {
   data[fld] = f.get(attr.name);
  } else {
   data[fld] = f.get(attr.name).toString();
  }
  fld++;
 }
 DataRow row = ROW_FACTORY.create(data, attributes);
 table.addDataRow(row);
}

ExampleSet exampleSet = table.createExampleSet();
return exampleSet;

The script execution returns a normal RapidMiner ExampleSet with metadata and data from the shapefile. Numeric attributes are converted correctly. If you have a Point geometry, you can easily extract the X and Y coordinates and display the data in a scatterplot (in this example all places in Hungary).

Places in Hungary
Places in Hungary. Shapefile from Geofabrik imported into RapidMiner. 
Data: © OpenStreetMap Contributors

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert