Workshop - Erweiterter GND Abgleich mit lobid

Folie - Erweiterter GND Abgleich mit lobid Folie - 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 erstellt mit OpenRefine Version 3.5.0.
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.

Versuch 6: (Maria OR Marie) AND dateOfBirth:[1850 TO 1875] AND dateOfDeath:<1939 AND placeOfBirth.id:“https://d-nb.info/gnd/4079048-4”

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.

Bonusversuch 7: (Maria OR Marie) AND dateOfBirth:[1850 TO 1875] AND dateOfDeath:<1939 AND placeOfBirth.id:“https://d-nb.info/gnd/4079048-4” AND professionOrOccupation.id:(“https://d-nb.info/gnd/4219058-7” OR “https://d-nb.info/gnd/4337175-9” OR “https://d-nb.info/gnd/4202451-1”)

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.

OperatorenBeispielBedeutung
[, ][1939-09-01 TO 1945-09-02]Einschließende “Range-Query”.
{, }{0 TO 100}Ausschließende “Range-Query” (1-99).
>, >=, <, <=<2000Offene Einschränkung auf Bereiche.
AND, OR, NOT, (, )(a OR b) AND NOT cBoolsche Operatoren und Gruppierungen.
+, -+Hund -KatzeBegriffe explizit ein- bzw. ausschließen.
~, ~3unschraf~2Unscharfe Suche mit erlaubtem Abstand.
"...""des Pudels Kern"Exakte Suche (Phrasensuche).
"..."~3"des Pudels Kern"~3Unscharfe Suche in Phrase.
^Wichtig^5Boosting/Gewichtung einzelner Suchbegriffe.
?M?ierEin unbekannter Buchstabe.
*Politik*Kein/mehrere unbekannte Buchstaben.
:type:PersonSuche in bestimmten Feldern.
_exists__exists_:dateOfBirthNur Einträge mit Geburtsdatum.
feld.\*hasBirthPlace.\*:WarschauGeburtsort 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.

Bildschirmfoto des Reconciliation Dialogs in OpenRefine.
Bildschirmfoto des Reconciliation Dialogs in OpenRefine.

Das schauen wir uns direkt in OpenRefine an und laden dafür die folgende Datei in ein Projekt.

💾 Wir benötigen die folgende Datei (Rechtsklick und “Ziel speichern unter…”):

Kretschmann Kabinett III mit Fehlern

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.

Bildschirmfoto des Projektes direkt nach dem Import.
Bildschirmfoto des Projektes direkt nach dem Import.

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.

Bildschirmfoto des Projektes nach den Transformationen.
Bildschirmfoto des Projektes nach den Transformationen.

Abgleich durchführen

Den Reconciliation Vorgang starten wir mit “Name" "Reconcile" "Start reconciling” und den in Abbildung 4 gezeigten Einstellungen.

Bildschirmfoto der Einstellungen für den Reconciliation Dialog.
Bildschirmfoto der Einstellungen für den Reconciliation Dialog.

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.

Update 15. Juni 2022: Der beschriebene Workaround ist mit der Umsetzung von Use ElasticSearch validation endpoint to check queries before executing them nicht mehr notwendig.

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.

Benjamin Rosemann
Benjamin Rosemann
Data Scientist

Ich evaluiere KI- und Software-Lösungen und integriere sie in den Archivalltag.

Ähnliches