Wortwolken mit Python

4 Minuten zum Lesen

Python setzt für alles, was Natural Language Processing (NLP) und die Verarbeitung von Text angeht, den Gold-Standard.1 Es gibt für Python zahlreiche mächtige Module, die den Umgang mit Daten enorm vereinfachen. Das gilt für strukturierte, also für Computer besonders leicht zu verarbeitende Daten, wie für unstrukturierte. Die Sorte von Daten, mit denen es Historiker meist zutun haben, sind Textdaten. Sie gelten als unstrukturiert, weil ein Computer zunächst die einzelnen Zeichen, aus denen ein Text besteht, in Zahlen übersetzen muss, um mit ihnen arbeiten zu können. Auch hier stellt Python großartige Hilfsmittel zur Verfügung. Eines davon möchte ich in diesem Blog vorstellen: wordcloud.

Sinn und Unsinn von Wortwolken

Wortwolken sind verführerisch.2 Sie verbinden für einen Text anscheinend einschlägige Wörter mit einer ästhetisch ansprechenden Darstellung. Oftmals nutzen sie unterschiedliche Farben und Größen. Mitunter verteilen sie die Wörter geschickt, um sie möglichst passgenau in eine vorgegebene Form zu integrieren. Diese Kombination aus semantischem Gehalt, also der Bedeutung der einzelnen Wörter, und ihrer facettenreichen Darstellungsästhetik birgt die Gefahr, Wortwolken misszuverstehen.

Für gewöhnlich folgen Wortwolken einigen einfachen Grundsätzen:

  1. Wortwolken zeigen in der Regel die häufigsten Wörter eines Textes. Da es zahlreiche Wörter gibt, die unabhängig vom Text häufiger als andere vorkommen, werden diese sogenannten ‘Stopwords’ zuerst herausgefiltert, bevor die Wortwolke erstellt wird.
  2. Die Größe und Farbe signalisieren normalerweise unterschiedliche Grade der Häufigkeit. Wörter dergleichen Farbe und/oder dergleichen Größe kommen also etwa gleichhäufig im Text vor.
  3. Die Maske, in die eine Wortwolke eingefügt wurde, ist, falls überhaupt vorhanden, willkürlich gewählt.

Aus alldem folgt: Wortwolken suggerieren zwar einen semantischen Zusammenhang zwischen ihrer Form und dem Inhalt des Textes, aus dem sie errechnet wurden. Wenn aber Algorithmen sie erstellt haben, geben sie genau genommen nur Auskunft über Worthäufigkeiten. Sie treffen keinerlei Aussagen darüber, worum es im Text inhaltlich geht. Denn die Bedeutung eines Textes erschließt sich nicht zuletzt darin, was er gerade nicht explizit macht.

Ein Beispiel dafür ist Kleists Nouvelle Die Marquise von O. Eine Wortwolke aus dem Text, den das Projekt Gutenberg zur Verfügung stellt, zeigt besonders prominent die Worte ‘Marquise’, ‘Mutter’, ‘Graf’, ‘Kommandant’, ‘Frau’ sowie zahlreiche Verben des Sagens. Dass der Text eigentlich von einer Vergewaltigung handelt, die er zwar nie ausdrücklich anspricht, sondern nur andeutet, geht aus der Wortwolke nicht hervor.

Wortwolke zu Kleist Marquise von O.

Nichtsdestoweniger erhält man durch die Wortwolke einen Eindruck vom Text. Man erfährt, um welche Personen er sich dreht, dass er von einer Familienangelegenheit handelt und dass die Kommunikation der Protagonisten von zentraler Bedeutung für das geschilderte Geschehen ist.

Hinsichtlich des Aussagewerts von Wortwolken ist also Vorsicht angebracht. Sie können zwar durchaus Auskunft über den Text geben. Aber sie bieten keine Interpretation des Inhalts, sondern machen quantifizierbare Merkmale sichtbar, die wiederum interpretiert werden müssen.

Wortwolken, programmatisch

Wortwolken lassen sich auf vielfältige Weise erstellen. Beinahe jede moderne Programmiersprache bietet dazu Bibliotheken an. In Python ist es besonders einfach.

Als erstes bindet man die notwendigen Module ein. Wir verwenden wordcloud von Andreas Mueller, um die nötigen Berechnungen vorzunehmen. Mit matplotlib stellen wir die Wortwolke dar. Das Modul wordcloud bietet auch eine Reihe von englischen Stopwords an. Möchte man deutsche Stopwords nutzen, empfehle ich das Module stop-words von Alireza Savand. Da ich für diesen Beitrag die Wortwolke in einer Maske erstellen möchte, benötigen wir außerdem noch pillow und numpy.

import numpy as np
import matplotlib.pyplot as plt

from PIL import Image
from wordcloud import WordCloud, STOPWORDS

Anschließend öffne ich die Text-Datei, aus der ich eine Wortwolke genieren möchte. Ich entscheide mich diesmal für Jane Asutens Pride and Prejudice, das auch über das Gutenberg-Projekt geladen werden kann. Als Maske nehme ich einen Scheerenschnitt von Austen, der über Wikipedia zu finden ist. Bevor ich die Grafik allerdings importieren kann, muss ich sie noch in das JPG-Format exportieren. Dabei hilft mir Gimp. Ich lade die Grafik und wandele sie mithilfe von numpy in einem Schritt in einen Array um. Außerdem ergänze ich die englischen Stopwords um die Wörter ‘said’, ‘Mr’ und ‘Mrs’ und erstelle einen Verweis auf die Variable blacklist.

with open('data/Auten_Pride_and_Prejudice.txt', 'r') as f:
    text = f.read()

austen_mask = np.array(Image.open('data/JaneAustenSilhouette.jp.'))

blacklist = STOPWORDS.union({'said', 'Mr', 'Mrs'})

Jetzt bleibt nur noch, eine Instanz der Wortwolke zu erstellen. Ich möchte einen weißen Hintergrund, nutze austen_mask als Maske und blacklist als Stopwords. Danach übergebe ich der Instanz den eingelesenen Text, erstelle ein Bild von der Wortwolke, aber ohne unnötige Achsen und lasse es mir anzeigen.

wc = WordCloud(background_color='white', mask=austen_mask, stopwords=blacklist)

wc.generate(text)

plt.imshow(wc, interpolation="bilinear")
plt.axis('off')

plt.show()

Als Ergebnis erhalte ich dann die folgende Wortwolke:

Wortwolke zu Austens *Pride and Prejudice*

Wortwolke zu Austens Pride and Prejudice


Auch in diesem Fall sind die Namen der Protagonisten deutlich zu erkennen. Im Gegensatz zu Kleist Novelle treten Wörter wie ‘think’, ‘know’, ‘wish’ und ‘hope’, aber auch ‘shall’, ‘must’, ‘may’, ‘might’ und dergleichen in den Vordergrund. Die Häufigkeit dieser Wörter legt also die Vermutung nahe, bei Austens Text gehe es nicht zuletzt um die Reflexion gesellschaftlicher Konventionen und Zwänge. Ein Befund, der nicht überrascht.

Das fertige Notebook

Ein Jupyter Notebook mit dem kompletten Code ist auf Gisthub hinterlegt.

  1. Ein hervorragender Einstieg in das Thema NLP und Python bieten das Natural Language Tool Kit (NLTK) und das Buch von Sarkar, Dipanjan: Text Analytics with Python. A Practical Real-World Approach to Gaining Actionable Insights from your Data, New York: Apress 2016. 

  2. Vgl. auch den Eintrag bei Wikipedia