In diesem Notebook verwenden wir den Text "Der Mann von vierzig Jahren" von Jakob Wassermann. Dieser Text stammt aus dem Jahr 1913 und wurde vom Projekt Gutenberg digitalisiert (http://www.gutenberg.org/ebooks/15736). Um die Arbeit mit dem Text zu erleichtern, habe ich die Metadaten und Copyright-Hinweise aus dem Text entfernt und in eigene Dateien ausgelagert. Die vollständige Fassung ist unter der oben angeführten Adresse abrufbar. Die Gutenberg-Lizenz erfordert die Angabe des folgendes Textes:
This eBook is for the use of anyone anywhere at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.net
Übung: Wir wollen den gesamten Inhalt des Romans ein einen einzigen String mit dem Namen text
einlesen. Die einzulesende Datei ist ../data/wassermann/der_mann_von_vierzig_jahren.txt
.
In [ ]:
#TODO
Wie haben bereits den Datentyp str
kennengelernt und uns mit Sequenztypen wie list
beschäftigt. Da auch str
ein Sequenztyp ist, stellten Strings ähnliche Schnittstellen bereit wie andere Sequenztypen. Wir können die Länge des Strings mit der Funktion len()
ermitteln:
In [ ]:
# TODO
Mit dem in
Operator können wir feststellen, ob ein Zeichen oder ein Substring im String enthalten ist. Gibt es im Text ein Y
?
In [ ]:
'Y' in text
Kommt das Wort "Brandung" im Text vor?
In [ ]:
# TODO
So wie man mit der count()
-Methode zählen kann, wie oft ein Wert in einer Liste oder einem Tupel erscheint, kann auch gezählt werden, wie oft ein Zeichen oder eine Abfolge von Zeichen in einem String vorkommen:
In [ ]:
text.count('Brandung')
In [ ]:
text.index('Brandung')
Übung: Wie könnten wir ermitteln, wo das zweite Vorkommen des Wortes Brandung
beginnt?
In [ ]:
Ähnlich wie index()
das erste Vorkommen eines Zeichens oder Teilstrings ermittelt, kann mit rindex()
das letzte Vorkommen gefunden werden.
Die Methode upper()
wandelt alle Zeichen eines Strings in Großbuchstaben um. lower()
wandelt alle Zeichen in Kleinbuchstaben um.
Der vermutlich häufigste Einsatzzweck von upper()
und lower()
liegt darin, unabhängig von Groß- und Kleinschreibung im Text suchen zu können.
In [ ]:
text.count('genau')
In [ ]:
text.count('Genau')
Übung: Überlegen Sie, wie alle Vorkommen von 'Genau' und 'genau' mit einer count()
-Anweisung gefunden werden könnten.
In [ ]:
Erzeugen Sie eine Variante von text
, die nur Kleinbuchstaben enthält, und die unter dem Namen lc_text
verfügbar gemacht wird.
In [ ]:
# TODO
In [ ]:
s = 'Mississippi'
s.replace('s', 'b')
Wir können uns das zunutze machen, um im Wassermann-Text alle nicht benötigten Zeilenumbrüche zu entfernen.
In [ ]:
text.replace('\n', ' ')
Allerdings müssen wir hier etwas aufpassen: Absätze werden durch zwei aufeinander folgende Zeilenumbrüche gekennzeichnet. Wenn wir die Absätze erhalten wollen, dürfen wir nur einfache Zeilenumbrüche durch ein Leerzeichen entfernen. Hat jemand eine Lösung dafür?
In [ ]:
# TODO
In [ ]:
tokens = lc_text.split()
tokens[:20]
Damit haben wir einen primitiven Tokenizer, der unseren Text in einzelne Wörter zerlegt.
Übung: Aus wie vielen Tokens (Wörtern) besteht der Text?
In [ ]:
Übung: Aus wie vielen Types besteht der Text? (Types sind unterschiedliche bzw. distinkte Tokens - man verwirft mehrfach vorkommende Tokens)
In [ ]:
Übung: wie hoch ist die Type-Token-Ratio? (Die Type-Token-Ratio ist ein Wert zwischen 0 und 1, der einein Indikator für den Wortschatz des Autors darstellt.)
In [ ]:
Falls nicht an Whitespace, sondern an einem anderen Zeichen gesplittet werden soll, kann dieses Zeichen (oder eine Zeichenkette) angegeben werden. Wenn wir von der naiven Annahme ausgehen, dass jeder Satz durch einen Punkt begrenzt wird, können wir den Text so in Sätze zerlegen:
In [ ]:
sentences = text.split('.')
Falls nicht an jedem Trennzeichen gesplittet werden soll, sondern z.B. nur beim ersten, kann maxsplit
gesetzt werden. Falls wir also nur am ersten Satz interessiert sind:
In [ ]:
text.split('.', 1)
Übung: Splitten Sie den Text absatzweise.
In [ ]:
Das String-Objekt kennt eine Reihe von Methoden, über die sich Stringvergleiche durchführen lassen.
startswith(str)
und endswith(str)
können dazu verwendet werden um Tokens zu finden, die mit einer bestimmten Zeichenfolge beginnen oder enden. Die Token, die mit der Silbe ab
beginnen, finden wir so:
In [ ]:
[token for token in tokens if token.startswith('ab')]
Es wäre schön, wenn hier jedes Wort nur einmal erscheinen würde. Wie das geht, wissen wir ja schon:
In [ ]:
Außerdem wollen wir die Ausgabe alphabetisch sortiert:
In [ ]:
Die Token, die mit der Zeichenkette heit
enden, können wir statt mit einer List Comprehension auch in einer Schleife suchen:
In [ ]:
result = []
for token in tokens:
# TODO
pass
Zahlen im Text finden wir so:
In [ ]:
[token for token in tokens if token.isdigit()]
In [ ]:
with open('../data/stopwords_de.txt') as fp:
stopwords = [word.rstrip() for word in fp.readlines()]
stopwords
Um nun die Stopwords aus der Liste tokens
zu entfernen, können wir eine List Comprension verwenden:
In [ ]:
print(len(tokens))
tokens = [token for token in tokens if token not in stopwords]
len(tokens)
Um Variablen in Strings einzubauen kennt Python mehrere Möglichkeiten. Die zur Zeit empfohlene ist die Methode format()
, die wir schon mehrfach verwendet haben. Die Idee dahinter ist, dass man in einen String Platzhalter einstreut, die mit format()
befüllt werden.
In [ ]:
print('Mein Name ist {}. Ich wohne in {}.'.format('Gunter', 'Graz'))
Falls wir einen Wert mehrfach benötigen, können wir die Platzhalter durchnummerieren:
In [ ]:
print('Ihr Name ist {0}. Sie wohnen in {1}. Der Name "{0}" hat {2} Buchstaben'. format('Gunter', 'Graz', len('Gunter')))
Wir können die Platzhalter aber auch benennen:
In [ ]:
print('Ihr Name ist {name}. Sie wohnen in {ort}. Der Name "{name}" hat {laenge} Buchstaben'. format(
name='Gunter', ort='Graz', laenge=len('Gunter')))
Auf diese Weise ist es relativ einfach, einen Märchengenerator zu schreiben:
In [ ]:
# Wir verwenden eine Zufallsgenerator zur Auswahl der Listenelemente
import random
things = ['Kind', 'Pferd', 'Elch', 'Haus', 'Pirat', 'Gespenst',
'Buch', 'Spiel', 'Stier', 'Ochse', 'Soldat', 'Bauer']
names = ['Stefan', 'Simon', 'Jakob', 'Moritz', 'Selma', 'Rita',
'Mama', 'Oma', 'Papa', 'Opa']
places = ['Wald', 'Regenbogen', 'Kanal', 'Fluss', 'Knast',
'Keller', 'Zoo']
print("""Es war einmal ein {thing1}. Sein Name war {name1}.
{name1} liebte {name2}. {name2} war ein {thing2}.
{name1} und {name2} gingen in den {place1} und erlebten dort
viele Abenteuer. Und wenn sie nicht gestorben sind, dann
leben sie noch heute.""".format(
name1=random.choice(names), name2=random.choice(names),
thing1=random.choice(things), thing2=random.choice(things),
place1=random.choice(places)))
In [ ]: