Workshop - Erweiterter GND Abgleich mit lobid
In diesem Tutorial vertiefen wir den Abgleich von Daten mit der GND über das lobid API.
Einführung
Reconciling in der OpenRefine Dokumentation.
OpenRefine API in der lobid API Dokumentation.
GND reconciliation (advanced) im lobid Blog.
Komplexe Suchanfragen im lobid Blog.
Query string syntax in der Elasticsearch Dokumentation.
Dieser Workshop wurde zuletzt getestet mit OpenRefine Version 3.8.2.
Das von lobid zur Verfügung gestellte API zur Nutzung der Gemeinsamen Normdatei (GND) verwendet unter der Haube die Suchtechnologie Elasticsearch. Wie andere Suchmaschinen kennt auch Elasticsearch Möglichkeiten eine Suchanfrage zu präzisieren. Durch Verwendung von besonderen Zeichen (Operatoren) können sehr komplexe Suchanfragen gestellt werden.
Die genauen Details sind unter Query string syntax in der Elasticsearch Dokumentation zu finden. Es sind bei dem lobid API jedoch nicht alle Features der “Abfragesprache” aktiviert. Im Zweifel die entsprechenden Operatoren erst einmal an einem Beispiel ausprobieren.
Aufgabe 1: Operatoren in der Weboberfläche
Wir führen die Operatoren zur Verbesserung der Suchergebnisse an (Such-)Beispielen ein, welche wir Stück für Stück weiter entwickeln. Da sich sowohl die Inhalte der GND, als auch die Algorithmen von Elasticsearch immer wieder ändern, ist es möglich, dass sich die Ergebnisse zu einem späteren Zeitpunkt von den hier beschriebenen unterscheiden.
Beispiel 1: Maria oder Marie?
Wir suchen eine Frau mit Vornamen Maria
oder Marie
und lernen dabei einige Sprachbestandteile kennen, mit denen wir die Suche in der GND via der lobid Weboberfläche einschränken können.
Die Links verweisen zum Ergebnis in der lobid Weboberfläche.
Versuch 1: Maria Marie.
Diese Anfrage macht jetzt nicht das, was wir (vielleicht) erwarten würden.
Mit dieser Anfrage wird nach Einträgen gesucht, die sowohl Maria als auch Marie beinhalten (Maria AND Marie
).
Die Verknüpfung via AND
ist die Standardeinstellung.
Dies können wir für unsere Anfrage anpassen, indem wir boolsche Operatoren wie AND
, OR
und NOT
explizit verwenden.
Versuch 2: Maria OR Marie
Nun finden wir sowohl Personen mit Vornamen Maria, als auch mit Vornamen Marie. Aber auch viele andere Ergebnisse, wie zum Beispiel Lieder mit dem Titel “Maria”. Wir benötigen also weitere Einschränkungen für die mehr als 100.000 Treffer.
Versuch 3: (Maria OR Marie) AND dateOfBirth:[1850 TO 1875]
Wir wissen, dass die Person zwischen 1850 und etwa 1875 geboren wurde.
Das können wir mit einer Range-Query auf dem Feld dateOfBirth
durchführen.
Bitte auch die Klammerung beim ersten Ausdruck (Maria OR Marie)
und die Verknüpfung mit AND
beachten!
Ein weiterer Vorteil einer Einschränkung über das Feld dateOfBirth
ist, dass wir uns die zusätzliche Einschränkung auf type:Person
sparen, da in der GND hauptsächlich Personen ein Geburtsdatum haben.
Versuch 4: (Maria OR Marie) AND dateOfBirth:[1850 TO 1875] AND dateOfDeath:<1939
Wir wissen außerdem, dass die Person den Ersten Weltkrieg erlebt hat, den Zweiten jedoch nicht.
Das könnten wir wieder über eine Range-Query abbilden: [1918-11-11 TO 1939-01-01}
.
Geschweifte Klammern {
, }
zeigen dabei an, dass der entsprechende Wert nicht in den Bereich eingeschlossen wird.
Also [2000 TO 2022]
hat die gleiche Bedeutung wie {1999 TO 2023}
.
Wir haben für den Ausdruck stattdessen einen der Vergleichsoperatoren <
, <=
, >
, >=
verwendet.
Versuch 5: (Maria OR Marie) AND dateOfBirth:[1850 TO 1875] AND dateOfDeath:<1939 AND placeOfBirth:Warschau
Wir wissen, dass die Person in Warschau geboren wurde.
Die Anfrage liefert aber keine Ergebnisse.
Das liegt daran, dass der Geburtsort nicht mit einem Wert, sondern mit einem anderen Objekt in der GND verknüpft ist.
Eine Möglichkeit trotzdem ein Ergebnis zu bekommen ist mit placeOfBirth.\*:Warschau
alle Felder des verknüpften Objektes zu durchsuchen.
Die präzisere Variante ist die GND-Nummer des Ortes zu verwenden.
Diese wird dann in Anführungsstriche "..."
gesetzt, da wir hier eine exakte Phrasensuche durchführen.
Es ist inzwischen klar, dass wir nach Marie Curie suchen. Zur Übung nehmen wir jedoch noch eine weitere Einschränkung vor: Wir wissen, dass die Person eine Naturwissenschaftlerin war. Entweder Chemikerin, oder Physikerin oder beides.
Die Berufe sind ebenfalls als Objekte verknüpft über professionOrOccupation
und können mit OR
verknüpft mit in die Anfrage aufgenommen werden.
Das ist ein Beispiel, wie die unterschiedlichen Anforderungen einer Personenrecherche in die “Suchsprache” von lobid-gnd/Elasticsearch übertragen werden können. Es gibt noch weitere Operatoren, die nicht mehr in das obige Beispiel reingepasst haben.
Beispiel 2: Das nicht!
Manchmal kommt es vor, dass die Ergebnisse von nicht gesuchten Einträgen überschwemmt werden. So gibt es für die Suchanfrage Freiburg tausende Ergebnisse aus allen Kategorien. Ein typisches Vorgehen ist, die Anfrage auf einen bestimmten Entitätstyp einzuschränken Freiburg AND type:PlaceOrGeographicName.
Neben einschränkenden Filtern gibt es auch ausschließende. So können wir in der Anfrage mit NOT
alle Einträge mit Freibug ausschließen, die in Baden-Württemberg vorkommen: Freiburg AND type:PlaceOrGeographicName AND NOT geographicAreaCode.id:“https://d-nb.info/standards/vocab/gnd/geographic-area-code#XA-DE-BW”.
Wir können auch mit +
und -
betonen welche Begriffe wir explizit suchen bzw. ausschließen: +Freiburg AND type:PlaceOrGeographicName AND -Breisgau.
Beispiel 3: Ungenaue Suche
Manchmal kennen wir die genaue Schreibweise eines Namens nicht, oder es gibt mehrere Varianten. Zum Glück ist die GND üblicherweise sehr großzügig alternative Schreibweisen eines Namens zu listen, so dass mit dem Suchbegriff Tschaikowski auch der gesuchte Komponist Čajkovskij zu finden ist.
Bei weniger bekannten Personen, oder unpraktischen OCR- oder Tippfehlern ist das komplizierter.
Zum Beispiel gibt es zum Zeitpunkt des Schreibens dieses Tutorials für Eleonore Prockaska keine Treffer. Mit dem Unschärfeoperator ~
und einer Distanz von 1
Eleonore Prockaska~1 finden wir die gesuchte Elenonore Prochaska auf Anhieb.
Ebenfalls hilfreich bei ungenauen Suchen sind die Operatoren ?
für ein unbekanntes Zeichen und *
für möglicherweise mehrere unbekannte Zeichen.
Beispielsweise findet die Anfrage Winfried Kretschmann AND dateOfBirth:1948 keine Ergebnisse, da bei Winfried Kretschmann das Geburtsdatum komplett (1948-05-17) angegeben ist. Mit dem Operator *
in der Anfrage Winfried Kretschmann AND dateOfBirth:1948* lässt sich das kompensieren.
Übersicht über die Operatoren
Es gibt noch mehr Operatoren, die wir hier nicht am Beispiel besprochen haben.
Dazu gehört die exakte Phrasensuche mit "..."
und das Boosting von einzelnen Begriffen mit ...^5
.
Operatoren | Beispiel | Bedeutung |
---|---|---|
[ , ] | [1939-09-01 TO 1945-09-02] | Einschließende “Range-Query”. |
{ , } | {0 TO 100} | Ausschließende “Range-Query” (1-99). |
> , >= , < , <= | <2000 | Offene Einschränkung auf Bereiche. |
AND , OR , NOT , ( , ) | (a OR b) AND NOT c | Boolsche Operatoren und Gruppierungen. |
+ , - | +Hund -Katze | Begriffe explizit ein- bzw. ausschließen. |
~ , ~3 | unschraf~2 | Unscharfe Suche mit erlaubtem Abstand. |
"..." | "des Pudels Kern" | Exakte Suche (Phrasensuche). |
"..."~3 | "des Pudels Kern"~3 | Unscharfe Suche in Phrase. |
^ | Wichtig^5 | Boosting/Gewichtung einzelner Suchbegriffe. |
? | M?ier | Ein unbekannter Buchstabe. |
* | Politik* | Kein/mehrere unbekannte Buchstaben. |
: | type:Person | Suche in bestimmten Feldern. |
_exists_ | _exists_:dateOfBirth | Nur Einträge mit Geburtsdatum. |
feld.\* | hasBirthPlace.\*:Warschau | Geburtsort mit Warschau in beliebigem Feld. |
Aufgabe 2: Nutzung in OpenRefine
Über das Reconciliation API für OpenRefine funktioniert die Nutzung der Operatoren für die Suche ähnlich. Wir wählen eine Spalte aus, deren Daten wir an den Reconciliation Service übermitteln wollen. Für diese Spalte können wir in dem in Abbildung 1 abgebildeten Dialog anschließend eine Typeinschränkung vornehmen. In der rechten Spalte können wir zusätzlich die Inhalte weiterer Spalten mit Feldern in der GND verknüpfen und mit übermitteln.
Das schauen wir uns direkt in OpenRefine an und laden dafür die folgende Datei in ein Projekt.
Kretschmann Kabinett III mit Fehlern💾 Wir benötigen die folgende Datei (Rechtsklick und “Ziel speichern unter…”):
In dieser Datei ist das Kabinett Kretschmann III. Wie in Abbildung 2 zu erkennen, sind die Namen mit OCR üblichen Fehlern versehen. Wir ignorieren die Spalte “GND-ID”, mit der wir die Namen sofort wieder korrekt aus der GND nachladen könnten. Diese Spalte benötigen wir später zur schnellen Überprüfung der Ergebnisse. Unser Szenario lautet daher: Wir haben eine Liste mit Namen, deren genaue Schreibweise wir nicht kennen, können diese Namen für den Abgleich jedoch mit einem ungefähren Geburtsdatum und einem Geburtsort ergänzen.
Transformation 1: Name fuzzy
Zuerst wollen wir dem lobid GND Reconciliation Service mitteilen, dass die Begriffe in der Spalte potentiell fehlerhaft sind.
Dafür haben wir in Aufgabe 1 den Fuzzy-Operator ~
kennen gelernt.
Wir transformieren also die Spalte via
“Name"
"Edit cells"
"Transform…”
und fügen mit dem folgenden GREL Ausdruck zu jedem Wort ~3
hinzu.
forEach(value.split(" "), v, v + "~3").join(" ")
Transformation 2: Geburtsdatum reduzieren
Bei den Geburtsdaten ist in der GND manchmal das komplette Geburtsdatum angegeben, manchmal aber auch nur das Geburtsjahr. Sollten unsere Daten genauer sein, als die in der GND, also wir das komplette Geburtsdatum haben, die GND aber nur das Geburtsjahr, oder umgekehrt, dann würden wir mit der Spalte Geburtsdatum richtige Treffer ausschließen.
Daher nehmen wir nur das Geburtsjahr und ergänzen das Wildcard-Zeichen *
via
“Geburtsdatum"
"Edit cells"
"Transform…”
und dem folgenden GREL Ausdruck.
value.split("-")[0] + "*"
Transformation 3: Geburtsort ergänzen
Über den lobid GND Reconciliation Service können wir auch direkt verknüpfte Objekte durchsuchen. Wir könnten im Reconciliation Dialog also direkt die Spalte “Geburtsort” mit der Eigenschaft “Geburtsort” in der GND verknüpfen.
Da wir die noch präzisere GND-ID des Geburtsortes haben, verwenden wir diese für unseren Abgleich.
Dafür muss die Spalte noch mit dem Präfix https://d-nb.info/gnd/
ergänzt werden.
Das funktioniert über
“Geburtsort (GND-ID)“
"Edit cells"
"Transform…”
und dem folgenden GREL Ausdruck.
"https://d-nb.info/gnd/" + value
Die für den Reconciliation Vorgang umgewandelten Spalten sind in Abbildung 3 abgebildet.
Abgleich durchführen
Den Reconciliation Vorgang starten wir mit “Name" "Reconcile" "Start reconciling” und den in Abbildung 4 gezeigten Einstellungen.
Durch die ergänzenden Spalten konnten bei unserem Experiment schon 11 von 13 Politikern mit hoher Konfidenz automatisch gematcht werden. Die restlichen Kandidaten matchen wir automatisch via “Name" "Reconcile" "Actions" "Match each cell to its best candidate”.
Um die Überprüfung der Ergebnisse automatisch vorzunehmen, speichern wir uns die GND-ID der vom Reconciliation Service gefundenen Treffer in einer neuen Spalte “Abgleich” über “Name" "Edit column" "Add column based on this column” und vergleichen sie dort direkt mit der Original “GND-ID” Spalte mit dem folgenden GREL Ausdruck.
cell.recon.match.id == row.cells["GND-ID"].value
Bei unserem Experiment waren alle Treffer korrekt (true
).
Weitere Operationen
Mit ähnlichen Transformationen können wir zum Beispiel auch “Range-Queries” oder andere Operatoren wie AND
, OR
, … erzeugen.
Jedoch gibt es mit manchen Operatoren (+
, -
, ^
, >
, <
, >=
, <=
) aktuell ein Problem, da sie von dem lobid GND Reconciliation API gefiltert und nicht an Elasticsearch weitergegeben werden.1
Daher benötigen wir zur Verwendung dieser Operatoren aktuell einen Workaround.2
Bei Anfragen an das lobid GND Reconciliation API mit Gruppierungen wie (... OR ...)
werden die oben genannten Operatoren nicht gefiltert. Wir können in OpenRefine also die Anfrage <1939
umwandeln in (<1939 OR <1939)
oder anstatt +Freiburg -Breisgau
können wir explizit (+Freiburg AND -Breisgau)
verwenden.
Fazit
Mit dem GND Reconciliation API als Aufbau auf die Suchtechnologie Elasticsearch verbindet die lobid Daten in OpenRefine mit den Daten der Gemeinsamen Normdatei. Die von Elasticsearch unterstützten Operatoren zur Einschränkung und Verbesserung der Suchergebnisse sind insbesondere beim Abgleich von großen Datenmengen ein sehr wertvolles Mittel, um auch für große Datenmengen eine übersichtliche Menge an idealerweise passenden Treffern automatisch zu ermitteln.
Im nächsten Teil beschäftigen wir uns mit dem erweiterten Datenabgleich zwischen OpenRefine und Wikidata.
Siehe Using range query parameter via OpenRefine Reconciliation auf GitHub. ↩︎
Eine Lösung ist mit Use ElasticSearch validation endpoint to check queries before executing them in Arbeit. ↩︎