<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.3 20210610//EN"
                  "http://jats.nlm.nih.gov/archiving/1.3/JATS-archivearticle1-3.dtd">
<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.3" article-type="other">
<front>
<journal-meta>
<journal-id></journal-id>
<journal-title-group>
<journal-title>forTEXT</journal-title>
</journal-title-group>
<issn publication-format="electronic">2943-212X</issn>
<publisher>
<publisher-name>Universitäts- und Landesbibliothek
Darmstadt</publisher-name>
<publisher-loc>Darmstadt</publisher-loc>
</publisher>
</journal-meta>
<article-meta>
<article-id pub-id-type="doi">10.48694/fortext.3809</article-id>
<title-group>
<article-title>Lerneinheit: Preprocessing mit NLTK</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<contrib-id contrib-id-type="orcid">0000-0002-7952-4194</contrib-id>
<name>
<surname>Schumacher</surname>
<given-names>Mareike</given-names>
</name>
<email>Mareike.Schumacher@sprachlit.uni-regensburg.de</email>
<xref ref-type="aff" rid="aff-1"/>
</contrib>
<contrib contrib-type="author">
<name>
<surname>Vauth</surname>
<given-names>Michael</given-names>
</name>
<email>michael.vauth@gmx.de</email>
</contrib>
<aff id="aff-1">
<institution-wrap>
<institution>Universität Regensburg</institution>
</institution-wrap>
</aff>
</contrib-group>
<volume>1</volume>
<issue>2</issue>
<issue-title>Korpusbildung</issue-title>
<pub-history>
<event>
<event-desc>Erstveröffentlichung: 04.04.2022 auf <ext-link ext-link-type="uri" xlink:href="https://fortext.net/routinen/lerneinheiten/preprocessing-mit-nltk">fortext.net</ext-link>
<date date-type="origdate" iso-8601-date="2022-04-04">
<day>04</day>
<month>04</month>
<year>2022</year>
</date>
</event-desc>
</event>
</pub-history>
<permissions>
<license license-type="open-access">
<ali:license_ref xmlns:ali="http://www.niso.org/schemas/ali/1.0/">https://creativecommons.org/licenses/by-sa/4.0/</ali:license_ref>
<license-p>-This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License.</license-p>
</license>
</permissions>
</article-meta>
</front>
<body>
<p><bold>Erstveröffentlichung:</bold> 04.04.2022 auf <ext-link ext-link-type="uri" xlink:href="https://fortext.net/routinen/lerneinheiten/preprocessing-mit-nltk">fortext.net</ext-link></p>
<sec id="eckdaten-der-lerneinheit">
  <title>Eckdaten der Lerneinheit</title>
  <list list-type="bullet">
    <list-item>
      <p>Anwendungsbezug: Textvorverarbeitung von Goethes <italic>Die
      Leiden des jungen Werthers</italic></p>
    </list-item>
    <list-item>
      <p>Methodik: Korpusbildung und
      <xref alt="Preprocessing" rid="glossary-preprocessing">Preprocessing</xref></p>
    </list-item>
    <list-item>
      <p>Angewendetes Tool: NLTK</p>
    </list-item>
    <list-item>
      <p>Lernziele: Einzelne Schritte zur Textbereinigung, wie z.B.
      Löschen von Leerzeilen, Entfernen von Stoppwörtern (vgl.
      <xref alt="Stoppwortliste" rid="glossary-stoppwortliste">Stoppwortliste</xref>)
      oder Tokenisierung (vgl.
      <xref alt="Type/Token" rid="glossary-type-token">Type/Token</xref>)
      auswählen und durchführen können</p>
    </list-item>
    <list-item>
      <p>Dauer der Lerneinheit: ca. 60 Minuten</p>
    </list-item>
    <list-item>
      <p>Schwierigkeitsgrad des Tools: mittel</p>
    </list-item>
  </list>
</sec>
<sec id="anwendungsbeispiel">
  <title>1. Anwendungsbeispiel</title>
  <p>Anhand einer Reintextversion (vgl.
  <xref alt="Reintext-Version" rid="glossary-reintext-version">Reintext-Version</xref>)
  von Goethes <italic>Die Leiden des jungen Werthers</italic> erlernen
  Sie in dieser Lerneinheit einige grundlegende Arbeitsschritte der
  Aufbereitung (vgl.
  <xref alt="Preprocessing" rid="glossary-preprocessing">Preprocessing</xref>)
  von Texten für digitale Analysen. Die Arbeitsschritte können
  unabhängig von Form und Inhalt des Textes oder des Korpus durchgeführt
  werden, das Sie analysieren möchten. Sie benötigen lediglich eine
  TXT-Version des Textes, den Sie untersuchen möchten. Achten Sie bei
  der Auswahl der Funktionen für eigene digitale Analysen aber darauf,
  ob sie zu den gewählten Methoden passen. Nutzen Sie z.B. Named Entity
  Recognition
  (<xref alt="Schumacher 2024a" rid="ref-schumacherLerneinheitNamedEntity2020" ref-type="bibr">Schumacher
  2024a</xref>;
  <xref alt="Schumacher 2024b" rid="ref-schumacherToolbeitragStanfordNamed2018" ref-type="bibr">Schumacher
  2024b</xref>) für maschinelles Lernen, so müssen Sie Ihr Korpus
  tokenisieren, d.h. in Ein-Wort-Listen umwandeln. Wenn Sie dagegen
  Topic Modeling
  (<xref alt="Horstmann 2024" rid="ref-horstmannMethodenbeitragTopicModeling2018" ref-type="bibr">Horstmann
  2024</xref>) anwenden möchten, brauchen Sie diesen Schritt nicht.
  Stattdessen ist es wichtig, Stoppwortlisten anwenden zu können.</p>
</sec>
<sec id="vorarbeiten">
  <title>2. Vorarbeiten</title>
  <p>Wir haben für diese Lerneinheit ein Jupyter Notebook
  (<xref alt="Kluyver u. a. 2016" rid="ref-kluyverJupyterNotebooksPublishing2016" ref-type="bibr">Kluyver
  u. a. 2016</xref>) vorbereitet, das Sie sowohl zum Erlernen als auch
  zum späteren Ausführen der Funktionen im Rahmen eigener Projekte
  nutzen können. Ein solches Notebook ermöglicht es Ihnen, die
  vorbereiteten kurzen Code-Einheiten per Klick aufzurufen. Installieren
  Sie bitte vorab
  <ext-link ext-link-type="uri" xlink:href="https://web.archive.org/save/https://www.anaconda.com/products/individual">Anaconda</ext-link>
  (<xref alt="Anaconda Software Distribution 2020" rid="ref-anacondasoftwaredistributionAnacondaDocumentation2020" ref-type="bibr">Anaconda
  Software Distribution 2020</xref>). Haben Sie Anaconda installiert, so
  nutzen Sie dieses Programm, um NLTK
  (<xref alt="Bird, Klein und Loper 2009" rid="ref-birdNaturalLanguageProcessing2009" ref-type="bibr">Bird,
  Klein und Loper 2009</xref>) zu installieren. Starten Sie dafür
  Anaconda und wechseln Sie links im Menü zu „Environments“. Geben Sie
  dann oben rechts in die Suchleiste „NLTK“ ein und wählen Sie im
  Drop-Down-Menü oben in der Mitte „All“. Im Suchergebnis erscheint nun
  eine Zeile für „NLTK - Natural Language Toolkit“, vor der links ein
  leerer Kasten steht.</p>
  <fig>
    <caption><p>Abb. 1: Suche nach „NLTK“ innerhalb von
    Anaconda</p></caption>
    <graphic mimetype="image" mime-subtype="png" xlink:href="Bildschirmfoto_2022-03-23_um_11.06.16.png" />
  </fig>
  <p>Klicken Sie in diesen Kasten, sodass dort ein kleiner Pfeil
  erscheint (vgl. Abb. 1) und gehen Sie dann auf den Button „Apply“
  unten rechts. Es kann einen Moment dauern bis das Programm Ihnen
  anzeigt, was die Installation von NLTK bedeutet, bzw. welche anderen
  Packages zusätzlich installiert oder aktualisiert werden müssen.
  Sobald Ihnen die Liste angezeigt wird, können Sie mit „Apply“ die
  Installation bestätigen (vgl. Abb. 2).</p>
  <fig>
    <caption><p>Abb. 2: Installation innerhalb von
    Anaconda</p></caption>
    <graphic mimetype="image" mime-subtype="png" xlink:href="GitMA-Lerneinheit2_0.png" />
  </fig>
  <p>Laden Sie nun den von uns vorbereiteten Goethe-Text und das Jupyter
  Notebook zum Preprocessing mit NLTK herunter. Gehen Sie dazu in unser
  <ext-link ext-link-type="uri" xlink:href="https://web.archive.org/save/https://github.com/forTEXT/forTEXT.net">forTEXT.net-GitHub-Repository</ext-link>
  und dort zunächst auf den grünen Button „Code“ und dann auf „Download
  ZIP“ (vgl. Abb. 3).</p>
  <fig>
    <caption><p>Abb. 3: forTEXT.net GitHub-Repository
    herunterladen</p></caption>
    <graphic mimetype="image" mime-subtype="png" xlink:href="Bildschirmfoto_2022-03-22_um_10.05.10.png" />
  </fig>
  <p>Entpacken Sie dann das ZIP-Archiv, indem Sie es in Ihrem
  Ordnersystem ausfindig machen und dieses doppelt anklicken. Gehen Sie
  nun zurück zu Anaconda. Klicken Sie links im Menü auf „Home“ und dann
  in der Kachel „Jupyter Notebooks“ auf „Launch“ (vgl. Abb. 4).</p>
  <fig>
    <caption><p>Abb. 4: Jupyter Notebook in Anaconda
    starten</p></caption>
    <graphic mimetype="image" mime-subtype="png" xlink:href="Bildschirmfoto_2022-03-21_um_13.58.55.png" />
  </fig>
  <p>Es öffnet sich dann ein Browser-Fenster, in welchem Sie Ihre
  Ordner-Struktur sehen. Navigieren Sie zu Ihrem Downloads-Ordner und
  dann in den gerade entpackten Ordner „Preprocessing mit NLTK“. Klicken
  Sie hier auf die Datei „Preprocessing mit NLTK.ipynb“, um das Notebook
  zu öffnen. Sie können nun der Anleitung im Notebook folgen. Falls Sie
  eine Auswahl unserer Codebeispiele lieber zu einem eigenen Notebook
  zusammenfassen wollen, finden Sie die einzelnen Schritte im Folgenden
  dokumentiert.</p>
</sec>
<sec id="funktionen">
  <title>3. Funktionen</title>
  <p>Für diese Lerneinheit haben wir das Preprocessing, mit dem Sie
  Texte für die digitale Analyse mit anderen Tools vorbereiten können,
  in zwei Komplexe unterteilt.</p>
  <p>Im ersten Komplex finden Sie Funktionen, mit denen Sie die Form
  eines Textes verändern können, ohne dabei inhaltlich einzugreifen. Mit
  diesen Funktionen können Sie</p>
  <list list-type="bullet">
    <list-item>
      <p>einen Text in einzelne Wörter oder Sätze unterteilen
      (Tokenisierung (vgl.
      <xref alt="Type/Token" rid="glossary-type-token">Type/Token</xref>)
      auf Wort- oder Satzebene)</p>
    </list-item>
    <list-item>
      <p>den gesamten Text in Kleinschreibung umwandeln</p>
    </list-item>
    <list-item>
      <p>doppelte Leerzeichen und Leerzeilen entfernen.</p>
    </list-item>
  </list>
  <p>Im zweiten Komplex finden Sie folgende Funktionen, mit denen Sie
  einzelne Elemente aus einem Text herauslöschen können: Wörter
  entfernen, die weniger als drei Zeichen haben. So können Sie damit
  meist solche Fehler eliminieren, die auf ein suboptimales
  <xref alt="OCR" rid="glossary-ocr">OCR</xref> zurückzuführen sind. Sie
  können außerdem:</p>
  <list list-type="bullet">
    <list-item>
      <p>Zahlen und Satzzeichen aus einem Text entfernen</p>
    </list-item>
    <list-item>
      <p>Sätze mit einer bestimmten Wortanzahl aus dem Text
      entfernen.</p>
    </list-item>
    <list-item>
      <p>eine Liste von Stoppwörtern (vgl.
      <xref alt="Stoppwortliste" rid="glossary-stoppwortliste">Stoppwortliste</xref>)
      (Wörter, die Sie in Ihrer Analyse nicht mit einbeziehen möchten)
      aus dem Text entfernen.</p>
    </list-item>
  </list>
  <p>Die Lerneinheit ist so aufgebaut, dass Sie jede Funktion einzeln
  ausführen können. Suchen Sie sich die Funktionen heraus, die Sie für
  Ihre Korpusvorbereitung (vgl.
  <xref alt="Preprocessing" rid="glossary-preprocessing">Preprocessing</xref>)
  brauchen. Funktionen, die Sie nicht benötigen, können Sie einfach
  überspringen. Um die Kombination unterschiedlicher
  Preprocessing-Schritte möglichst unkompliziert zu ermöglichen, stellen
  wir am Ende der Lerneinheit drei Preprocessing-Pipelines vor, die Sie
  ebenfalls benutzen können.</p>
  <sec id="nltk-laden">
    <title>NLTK laden<break/></title>
    <p>Bevor Sie mit dem Preprocessing Ihres Textes beginnen können,
    müssen Sie das NLTK-Package (Natural Language Processing Toolkit)
    und ein paar zusätzliche Packages laden. Diesen Schritt müssen Sie
    immer ausführen, unabhängig davon welchen Schritt oder welche
    Schritte des Preprocessings Sie übernehmen möchten. Sie können den
    folgenden Code einzeln ausführen oder vor den Code einer Funktion
    setzen.</p>
    <code language="python">import nltk  
import re  
import os</code>
  </sec>
  <sec id="daten-laden">
    <title>Daten laden<break/></title>
    <p>Als nächstes legen wir fest, welche Textdatei die nachfolgenden
    Preprocessing-Schritte nutzt und in welchem Verzeichnis diese liegt.
    In das Datenverzeichnis werden auch die bearbeiteten Dateien
    gespeichert.</p>
    <code language="python">data_dir = 'Daten'  
text_file = '1774-Werther.txt'</code>
    <sec id="funktionen-zur-anpassung-der-textform">
      <title>Funktionen zur Anpassung der Textform<break/></title>
      <p>Manche digitalen Methoden und Tools zur Textanalyse benötigen
      vorverarbeitete Dokumente, die eine ganz bestimmte Form aufweisen.
      Manchmal benötigen Sie z.B. eine Darstellung, in der in jeder
      Zeile ein Wort steht oder pro Zeile ein Satz. In der digitalen
      Stilometrie kann es manchmal sinnvoll sein, Texte so
      vorzubereiten, dass sie ausschließlich Kleinschreibung aufweisen,
      um die Großschreibung häufiger Wörter wie „der“, „die“ oder „das“
      am Satzanfang herauszunehmen. In diesem Abschnitt finden Sie
      Funktionen des Python-Packages NLTK, mit denen Sie solche
      Operationen durchführen können, die nicht in den eigentlichen
      Text, sondern nur in dessen Form eingreifen.</p>
    </sec>
    <sec id="tokenisierung-auf-wortebene">
      <title>Tokenisierung auf Wortebene<break/></title>
      <p>Mit der Funktion zur Tokenisierung können Sie Elemente in einem
      Text vereinzeln bzw. einzeln markieren. Mit NLTK können Sie
      Tokenisierung sowohl auf Wort- als auch auf Satzebene durchführen.
      Um die Tokenisierung auf Wortebene durchzuführen und den
      tokenisierten Text in einer neuen Datei zu speichern, klicken Sie
      nun in die unten stehende Box. Klicken Sie dann oben im Menü auf
      „Run“, um den Vorgang zu starten. Sobald links in den eckigen
      Klammern eine kleine Zahl erscheint, müsste das Programm eine neue
      Datei mit Ihren Daten in Ihrem Ordnersystem abgelegt haben.</p>
      <p>Dabei wird jedes Token in einer neuen Textzeile ausgegeben.</p>
      <code language="python">input_file = os.path.join(data_dir, text_file)  
basename = os.path.splitext(input_file)[0]

with open('Downloads/1774-Werther.txt', 'r', encoding='utf-8') as input:  
    text = input.read()

# Tokenisierung  
tokens = nltk.word_tokenize(text, 'german')

# Der join() Befehl verbindet Elemente einer Liste mit einem String.  
# Wir verwenden hier den Zeilenumbruch &quot;\\n&quot; als Verbindungselement, um eine vertikale Wortliste zu erstellen.

output_str = '\n'.join(tokens)

with open('Downloads/Werther_Tokens.txt', 'w', encoding='utf-8') as output:  
    output.write(output_str)</code>
    </sec>
    <sec id="tokenisierung-auf-satzebene">
      <title>Tokenisierung auf Satzebene<break/></title>
      <p>Um die Tokenisierung auf Satzebene durchzuführen und den
      tokenisierten Text in einer neuen Datei zu speichern, klicken Sie
      nun in die unten stehende Box. Klicken Sie dann oben im Menü auf
      „Run“, um den Vorgang zu starten. Sobald links in den eckigen
      Klammern eine kleine Zahl erscheint, müsste das Programm eine neue
      Datei mit Ihren Daten in Ihrem Ordnersystem abgelegt haben.</p>
      <p>Dabei wird jeder Satz in einer neuen Textzeile ausgegeben.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

sentences = nltk.sent_tokenize(text,language='german')  
output_str = '\n'.join(sentences)

with open(basename + '_Saetze.txt', 'w', encoding='utf-8') as output:  
    output.write(output_str)</code>
    </sec>
    <sec id="umwandlung-in-kleinschreibung">
      <title>Umwandlung in Kleinschreibung<break/></title>
      <p>Für manche Methoden und / oder manche Sprachen kann es sinnvoll
      sein, den gesamten Text in Kleinschreibung zu transformieren. Wenn
      Sie Ihren Text auf diese Weise umwandeln und das Ergebnis in einer
      neuen Datei speichern möchten, nutzen Sie dazu diese Code-Zeilen.
      Das Programm legt dann eine neue Datei mit dem unten aufgeführten
      Namen in Ihrem Ordnersystem ab.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

lower_text = text.lower()

with open(basename + '_Saetze_lowercase.txt', 'w', encoding='utf-8') as output:  
    output.write(lower_text)</code>
    </sec>
    <sec id="doppelte-leerzeichen-und-leerzeilen-entfernen">
      <title>Doppelte Leerzeichen und Leerzeilen
      entfernen<break/></title>
      <p>Manchmal kommen durch die Vorverabeitung oder auch durch die
      Digitalisierung Leerzeichen und -zeilen in Texte, die Sie
      vielleicht bei Ihren weiteren Verarbeitungsschritten stören
      können. Die folgenden Funktionen helfen Ihnen dabei, doppelte
      Leerzeichen und Leerzeilen zu entfernen.</p>
    </sec>
    <sec id="doppelte-leerzeichen-entfernen">
      <title>Doppelte Leerzeichen entfernen</title>
      <p>Wenn Sie doppelte Leerzeichen in Ihrem Text entfernen möchten,
      nutzen Sie dazu den folgenden Code. Ihr Ergebnis wird dann in
      einer neuen Datei gespeichert.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

# Mit der re.sub() Funktion können wir reguläre Ausdrücke verwenden, um bestimmte Textelemente zu entfernen.  
# Mehrfachvorkommen von Leerzeichen werden mit dem regulärem Ausdruck ' +' gefunden.  
# Um reguläre Ausdrücke auszuprobieren, kann man zum Beispiel diese Website verwenden: &lt;https://regexr.com/&gt;



clean_text = re.sub(' +', # der reguläre Ausdruck mit dem wir die Zeichen finden, die entfernt werden sollen.  
' ', # Was eingefügt werden soll. In diesem Fall ein einfaches Leerzeichen  
text # Der Text den wir bereinigen wollen.  
)

with open(basename + '_einfacheLeerzeichen.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_text)</code>
    </sec>
    <sec id="leerzeilen-entfernen">
      <title>Leerzeilen entfernen<break/></title>
      <p>Wenn Sie Leerzeilen in Ihrem Text entfernen möchten, nutzen Sie
      dazu den folgenden Code. Sobald links in den eckigen Klammern eine
      Zahl erscheint, wurde Ihr Ergebnis in einer neuen Datei
      gespeichert.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

# Mit diesem regulären Ausdruck suchen wir nach Mehrfachvorkommen von Zeilenumbrüchen.
clean_text = re.sub('\n+',' ',  text)</code>
      <p>with open(basename + ’_ohneLeerzeilen.txt’, ‚w‘,
      encoding=‚utf-8‘) as output: output.write(clean_text)</p>
    </sec>
    <sec id="funktionen-zum-herauslöschen-einzelner-elemente">
      <title>Funktionen zum Herauslöschen einzelner
      Elemente<break/></title>
      <p>Sie wissen nun, wie Sie formale Elemente Ihres Textes verändern
      können. Sie können auf Satz- und Wortebene tokenisieren,
      durchgängige Kleinschreibung bewirken und doppelte Leerzeichen
      sowie Leerzeilen entfernen. Für manche Methoden, wie z.B. das
      Topic Modeling oder auch word2vec (@
      <xref alt="Horstmann 2024" rid="ref-horstmannMethodenbeitragTopicModeling2018" ref-type="bibr">Horstmann
      2024</xref>;
      <xref alt="Schumacher 2024c" rid="ref-schumacherMethodenbeitragWord2vec2023" ref-type="bibr">Schumacher
      2024c</xref>) kann es sinnvoll sein, bei der Vorverarbeitung auch
      in den Text selbst einzugreifen. Von großer Bedeutung ist hier die
      Entfernung von Stopwörtern, d.h. Wörtern, die nicht in die Analyse
      einbezogen werden sollen. Auch das Entfernen von Zahlen,
      Interpunktionszeichen oder kurzen Wörtern oder Sätzen kann für
      einige Methoden der Digital Humanities sinnvoll sein. Wählen Sie
      sich die Funktionen, die Sie brauchen einfach aus den folgenden
      Blöcken aus und überspringen Sie diejenigen, die für Sie nicht
      sinnvoll sind.</p>
      <p>Bei manchen Funktionen können Sie wählen, in welchem Format Sie
      ihr Ergebnis abspeichern wollen. In diesem Fall finden Sie zu
      einer Funktion mehrere Abschnitte.</p>
    </sec>
    <sec id="entfernen-von-stoppwörtern">
      <title>Entfernen von Stoppwörtern<break/></title>
      <p>Das NLTK-Package stellt auch eine Reihe von Stopwortlisten für
      verschiedene Sprachen zur Verfügung. Im folgenden Beispiel führen
      Sie die Entfernung von Stopwörtern mit der Liste deutscher
      Stopwörter durch.</p>
      <code language="python">from nltk.corpus import stopwords  
from nltk.tokenize import word_tokenize

with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

language = 'german'  
token = word_tokenize(text, language)

# Wir verwenden eine List Comprehension, mit der nur die Token in die neue Liste übernommen werden, die nicht in der Stopwords Liste sind.  

filtered_token = [token for token in token if token not in stopwords.words(language)]

# Erneut erstellen wir eine vertikale Tokenliste, die in die neue Datei ausgegeben wird.  
clean_token = '\n'.join(filtered_token)

with open(basename + '_ohneStopwords.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_tokens)</code>
      <p>Wenn Sie Stoppwörter in einer anderen Sprache entfernen wollen,
      geben Sie in oben stehendem Code statt ‚german‘ einfach die
      Sprache ein, die Sie benötigen. Um eine Liste aller Sprachen zu
      bekommen, für die NLTK Stoppwortlisten bereitstellt, können Sie
      den folgenden Code nutzen.</p>
      <code language="python">from nltk.corpus import stopwords  
print(stopwords.fileids())</code>
    </sec>
    <sec id="entfernen-von-satzzeichen-und-zahlen">
      <title>Entfernen von Satzzeichen und Zahlen<break/></title>
      <p>Je nach Fragestellung die Sie untersuchen wollen, kann es
      sinnvoll sein, Satzzeichen und Zahlen, also alle
      nicht-alphabetischen Elemente, aus einem Text herauszufiltern.
      Wenn Sie Ihren Text oder Ihr Korpus auf diese Weise vorverarbeiten
      wollen, finden Sie hier dazu den Code.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

from nltk.tokenize import word_tokenize  
token = word_tokenize(text)

# Alle nicht-alphabetischen Zeichen werden herausgefiltert  
filtered_token = [token for token in token if token.isalpha()]  
clean_tokens = '\n'.join(filtered_tokens)

with open(basename + '_ohneSatzzeichenundZahlen.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_tokens)</code>
    </sec>
    <sec id="entfernen-von-zahlen">
      <title>Entfernen von Zahlen<break/></title>
      <p>Wenn Sie zwar Zahlen, aber keine Satzzeichen entfernen wollen,
      können Sie dafür den folgenden Code verwenden.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

# Hier verwenden wir wieder die re.sub() Funktion  
#'[0-9]' -- Der reguläre Ausdruck für Zahlen

text_without_numbers = re.sub('[0-9]','', text)


# Hier tokenisieren wir den bereinigten Text  
tokens = nltk.word_tokenize(text_without_numbers, 'german')  
clean_tokens = '\n'.join(tokens)

with open(basename + '_ohneZahlen.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_tokens)</code>
    </sec>
    <sec id="entfernen-von-satzzeichen">
      <title>Entfernen von Satzzeichen<break/></title>
      <p>Wenn Sie ausschließlich Satzzeichen aus Ihrem Text
      herausfiltern möchten, können Sie das mit diesem Code tun.</p>
      <code language="python">import string

with open(input_file, 'r', encoding='utf-8') as input:  
text = input.read()

from nltk.tokenize import word_tokenize  
tokens = word_tokenize(text)

# Filtern der Interpunktionszeichen
filtered_tokens = [token for token in tokens if token not in string.punctuation]

clean_tokens = '\n'.join(filtered_tokens)

with open(basename + '_ohneSatzzeichen.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_tokens)</code>
    </sec>
    <sec id="entfernen-kurzer-wörter">
      <title>Entfernen kurzer Wörter<break/></title>
      <p>Wörter, die nur aus drei Buchstaben oder weniger bestehen, sind
      häufig Funktionswörter. Ein anderer Grund, aus dem Sie evtl. kurze
      Wörter bei der Vorverarbeitung Ihres Korpus herausfiltern möchten,
      ist, dass Fehler, die durch mangelhafte OCR-Erkennung entstanden
      sein können, auf diese Weise minimiert werden können. OCR-Software
      erkennt manchmal Bindestriche am Seitenrand nicht und „zerhackt“
      dann die betroffenen Wörter.</p>
      <p>Wenn Sie aus oben genannten oder anderen Gründen Wörter einer
      bestimmten Länge aus Ihrem Text herausfiltern möchten, so können
      Sie das mit unten stehendem Code tun.</p>
      <p>Mit diesem Code filtern Sie Wörter aus einem Text heraus, die
      kürzer als drei Buchstaben sind. Möchten Sie Wörter bis zu einer
      anderen Länge aus Ihrem Text herausholen, so ersetzen Sie einfach
      die 3. Wenn Sie lange Wörter herausfiltern möchten statt kurze, so
      ändern Sie das &gt; Zeichen und machen Sie daraus &lt;. Passen Sie
      in diesem Fall auch die Zahl an.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

from nltk.tokenize import word_tokenize  
tokens = word_tokenize(text)

# Filtern nach der Tokenlänge 
filtered_tokens = [token for token in tokens  if len(token) &lt; 3]

clean_tokens = '\n'.join(filtered_tokens)

with open(basename + '_nurlangeToken.txt', 'w', encoding='utf-8') as output:  
    output.write(clean_tokens)</code>
    </sec>
    <sec id="entfernen-kurzer-sätze">
      <title>Entfernen kurzer Sätze<break/></title>
      <p>Wenn Sie Sätze einer bestimmten Länge aus Ihrem Text
      herausfiltern möchten, so können Sie dies mit unten stehendem Code
      tun. Passen Sie dazu den Dateipfad in der ersten Zeile so an, dass
      dieser zu Ihrem Text oder Textkorpus führt. Wenn Sie mit unserem
      Beispieltext arbeiten, müssen Sie hier evtl. gar nichts anpassen.
      Mit unserem Beispielcode können Sie Sätze aus einem Text
      herausfiltern, die kürzer sind als 4 Wörter; passen Sie die Zahl 4
      im Code also ggf. an. Elemente wie „Erster Theil“, die nicht zum
      eigentlichen Erzähltext gehören, sondern Formelemente sind,
      bekommen Sie damit aus Ihrem Text herausgerechnet. Bedenken Sie
      aber auch, dass derselbe Code auch Sätze wie „Aber halt!“ aus dem
      Text herauswirft, obwohl diese zum eigentlichen Erzähltext
      gehören. Nutzen Sie diesen Vorverarbeitungsschritt also bewusst
      und vorsichtig!</p>
      <p>Im Folgenden Finden Sie drei Varianten des Codes, die Ihnen
      unterschiedliche Output-Dateien ausgeben. Das erste Beispiel gibt
      Ihnen einen Fließtext, in dem alle (übrig gebliebenen) Tokens und
      Sätze als solche markiert sind.</p>
    </sec>
    <sec id="entfernen-kurzer-sätze-und-speichern-als-fließtext">
      <title>Entfernen kurzer Sätze und Speichern als
      Fließtext<break/></title>
      <p>Möchten Sie Sätze einer bestimmten Länge aus Ihrem Text
      herausrechnen und den Text in einer Datei als Fließtext
      abspeichern, in dem alle Wörter und Sätze als solche markiert
      sind, so können Sie dazu diesen Code nutzen.</p>
      <code language="python">from nltk.tokenize import sent_tokenize, word_tokenize

with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

sentences = nltk.sent_tokenize(text, 'german')  

# Filtern anhand der Tokenanzahl pro Satz
long_sentences = [sentence for sentence in sentences if len(word_tokenize(sentence, 'german')) &gt; 4]

# Hier fügen wir alle getrennten Sätze wieder zusammen.  
long_sentences_str = ' '.join(long_sentences)

with open(basename + '_langeSaetze_Fliesstext.txt', 'w', encoding='utf-8') as output:  
    output.write(long_sentences_str)</code>
    </sec>
    <sec id="entfernen-kurzer-sätze-und-speichern-mit-einem-satz-pro-zeile">
      <title>Entfernen kurzer Sätze und Speichern mit einem Satz pro
      Zeile<break/></title>
      <p>Möchten Sie Sätze einer bestimmten Länge aus Ihrem Text
      herausrechnen und den Text in einer Datei abspeichern, in der
      jeder Satz eine Zeile bildet und Wörter und Sätze nicht markiert
      sind, so nutzen Sie dazu unten stehenden Code.</p>
      <code language="python">with open(input_file, 'r', encoding='utf-8') as input:  
    text = input.read()

sentences = nltk.sent_tokenize(text, 'german')  
filtered_sentences = [sent for sent in sentences if len(nltk.word_tokenize(sentence, 'german')) &gt; 4]  
output_str = '\n'.join(filtered_sentences)

with open(basename + '_langeSaetze_Zeilen.txt', 'w', encoding='utf-8') as output:  
    output.write(output_str)</code>
      <p>Sie haben nun einige zentrale Funktionen zur Vorverarbeitung
      (Preprocessing) Ihrer Texte für eine digitale Analyse
      kennengelernt. Sie können die Funktionen alle auch einzeln nutzen.
      Speichern Sie sich unser Notebook also gerne ab und nutzen es
      immer dann, wenn Sie einzelne Funktionen davon zum Preprocessing
      brauchen.</p>
    </sec>
    <sec id="preprocessing-pipelines">
      <title>Preprocessing Pipelines<break/></title>
      <p>Um die Funktionen zu Textbereinigung, Wort-Tokenisierung und
      Satz-Tokenisierung übersichtlich und mit wenig Code zu verwenden,
      können wir auch Preprocessing Pipelines bauen. Wir stellen im
      folgenden 3 Pipelines vor, die Sie nutzen und weiterentwickeln
      können.</p>
    </sec>
    <sec id="text-pipeline">
      <title>Text Pipeline<break/></title>
      <code language="python"># Import des Regular Expression Package  
import re

class TextPipeline:  
    def __init__(self, input_file: str):  
        with open(input_file, 'r', encoding='utf-8') as input:  
            self.text = input.read()

    def remove_double_spaces(self):  
        self.text = re.sub(' +', ' ', self.text)

    def lowercase(self):  
        self.text = self.text.lower()

    def remove_blank_lines(self):  
        self.text = re.sub('\n+', ' ', self.text)

    def save(self, output_file: str = 'clean_text.txt'):  
        with open(output_file, 'w', encoding='utf-8') as output:  
            output.write(self.text)  

  
# Um die Text-Pipeline zu beginnen, geben wir den Dateinamen unseres Textes an:  

text_pipeline = TextPipeline(input_file='Daten/1774-Werther.txt')

# Jetzt können wir alle Bereinigungsschritte beliebig hinzufügen oder weglassen
text_pipeline.remove_double_spaces()  
text_pipeline.lowercase()  
text_pipeline.remove_blank_lines()

# Als letztes sichern wir die bereinigte Tokenliste und wählen dafür einen Dateinamen aus:  
text_pipeline.save(output_file='Daten/clean_text.txt')

# Wir können uns das Ergebnis aber zur Überprüfung zusätzlich hier ausgeben lassen:  
print(text_pipeline.text)</code>
    </sec>
    <sec id="token-pipeline">
      <title>Token Pipeline<break/></title>
      <code language="python">import string  
from nltk.tokenize import word_tokenize  
from nltk.corpus import stopwords

class TokenPipeline:  
# Die Klasse &quot;TokenPipeline&quot; enthält alle Bereinigungsfunktionen, die oben erklärt wurden. Weitere Bereinigungsschritte können ergänzt werden. Im ersten Schritt der Token-Pipeline wird der Text geladen und tokenisiert.  

    def __init__(self, input_file: str, language: str = 'german'):  
        with open(input_file, 'r', encoding='utf-8') as input:  
            text = input.read()  
        self.tokens = word_tokenize(text, language)  
        self.language = language

    def remove_stopwords(self):  
        self.tokens = [token for token in self.tokens if token not in stopwords.words(self.language)]

    def remove_short_token(self, min_len: int = 3):  
        self.tokens = [token for token in self.tokens if len(token) &gt;= min_len]

    def remove_numbers(self):  
        self.tokens = [token for token in self.tokens if not re.findall('[0-9]', token)]

    def remove_interpunctation(self):  
        self.tokens = [token for token in self.tokens if token not in string.punctuation]

    def save(self, output_file: str = 'clean_token.txt'):  
        token_str = '\n'.join(self.tokens)  
        with open(output_file, 'w', encoding='utf-8') as output:  
            output.write(token_str)

# Um die Token-Pipeline zu beginnen, geben wir den Dateinamen unseres Textes an:  
token_pipeline = TokenPipeline(input_file='Daten/1774-Werther.txt', language='german')

# Jetzt können wir alle Bereinigungsschritte beliebig hinzufügen oder weglassen
token_pipeline.remove_numbers()  
token_pipeline.remove_interpunctation()  
token_pipeline.remove_stopwords()  
token_pipeline.remove_short_token(min_len=4)

# Als letztes sichern wir die bereinigte Tokenliste und wählen dafür einen Dateinamen aus:  
token_pipeline.save(output_file='Daten/clean_token.txt')

# Wir können uns das Ergebnis aber zur Überprüfung zusätzlich hier ausgeben lassen:  
print(token_pipeline.tokens)</code>
    </sec>
    <sec id="satz-pipeline">
      <title>Satz Pipeline<break/></title>
      <code language="python">from nltk.tokenize import sent_tokenize, word_tokenize

class SentencePipeline:  
    def __init__(self, input_file: str, language: str = 'german'):  
    with open(input_file, 'r', encoding='utf-8') as input:  
        text = input.read()  
    self.sentences = sent_tokenize(text, language)  
    self.language = language

    def remove_short_sentences(self, min_len: int = 3):  
        self.sentences = [sentence for sentence in self.sentences 
        if len(word_tokenize(sentence, self.language)) &gt; min_len]

# hier können weitere Bereinigungsfunktionen ergänzt werden.

    def save_as_list(self, output_file: str = 'sententence_list.txt'):  
        sentence_str = '\n'.join(self.sentences)  
        with open(output_file, 'w', encoding='utf-8') as output:  
            output.write(sentence_str)

    def save_as_text(self, output_file: str = 'sententence_list.txt'):  
        sentence_str = ' '.join(self.sentences)  
        with open(output_file, 'w', encoding='utf-8') as output:  
            output.write(sentence_str)  
  
# Um die Sentence-Pipeline zu beginnen, geben wir den Dateinamen unseres Textes an:
sentence_pipeline = SentencePipeline(input_file='Daten/1774-Werther.txt', language='german')


# Jetzt können wir alle Bereinigungsschritte beliebig hinzufügen oder weglassen:
sentence_pipeline.remove_short_sentences()

# Als letztes sichern wir die bereinigte Tokenliste und wählen dafür einen Dateinamen aus:  
token_pipeline.save(output_file='Daten/clean_sentences.txt')

# Wir können uns das Ergebnis aber zur Überprüfung zusätzlich hier ausgeben lassen:  
print(sentence_pipeline.sentences)</code>
    </sec>
  </sec>
</sec>
<sec id="externe-und-weiterführende-links">
  <title>Externe und weiterführende Links</title>
  <list list-type="bullet">
    <list-item>
      <p>Anaconda:
      <ext-link ext-link-type="uri" xlink:href="https://web.archive.org/save/https://www.anaconda.com/products/individual">https://web.archive.org/save/https://www.anaconda.com/products/individual</ext-link>
      (Letzter Zugriff: 04.06.2024)</p>
    </list-item>
    <list-item>
      <p>forTEXT.net-GitHub-Repository:
      <ext-link ext-link-type="uri" xlink:href="https://web.archive.org/save/https://github.com/forTEXT/forTEXT.net">https://web.archive.org/save/https://github.com/forTEXT/forTEXT.net</ext-link>
      (Letzter Zugriff: 04.06.2024)</p>
    </list-item>
    <list-item>
      <p>REGEX:
      <ext-link ext-link-type="uri" xlink:href="https://web.archive.org/save/https://regexr.com/">https://web.archive.org/save/https://regexr.com/</ext-link>
      (Letzter Zugriff: 04.06.2024)</p>
    </list-item>
  </list>
</sec>
<sec id="glossar">
  <title>Glossar</title>
  <def-list>
    <def-item>
      <term><styled-content id="glossary-csv">CSV</styled-content></term>
      <def>
        <p>CSV ist die englische Abkürzung für <italic>Comma Separated
        Values</italic>. Es handelt sich um ein Dateiformat zur
        einheitlichen Darstellung und Speicherung von einfach
        strukturierten Daten mit dem Kürzel <monospace>.csv</monospace>
        , sodass diese problemlos zwischen IT-Systemen ausgetauscht
        werden können. Dabei sind alle Daten zeilenweise angeordnet.
        Alle Zeilen wiederum sind in einzelne Datenfelder aufgeteilt,
        welche durch Trennzeichen wie Semikola oder Kommata getrennt
        werden können. In Programmen wie Excel können solche Textdateien
        als Tabelle angezeigt werden.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-lemmatisieren">Lemmatisieren</styled-content></term>
      <def>
        <p>Die Lemmatisierung von Textdaten gehört zu den wichtigen
        <xref alt="Preprocessing" rid="glossary-preprocessing">Preprocessing</xref>-Schritten
        in der Textverarbeitung. Dabei werden alle Wörter
        (<xref alt="Token" rid="glossary-type-token">Token</xref>) eines
        Textes auf ihre Grundform zurückgeführt. So werden
        beispielsweise Flexionsformen wie „schneller“ und „schnelle“ dem
        Lemma „schnell“ zugeordnet.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-ocr">OCR</styled-content></term>
      <def>
        <p>OCR steht für <italic>Optical Character Recognition</italic>
        und bezeichnet die automatische Texterkennung von gedruckten
        Texten, d.h. ein Computer „liest“ ein eingescanntes Dokument,
        erkennt und erfasst den Text darin und generiert daraufhin eine
        elektronische Version.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-preprocessing">Preprocessing</styled-content></term>
      <def>
        <p>Für viele digitale Methoden müssen die zu analysierenden
        Texte vorab „bereinigt“ oder „vorbereitet“ werden. Für
        statistische Zwecke werden Texte bspw. häufig in gleich große
        Segmente unterteilt (<italic>chunking</italic>), Großbuchstaben
        werden in Kleinbuchstaben verwandelt oder Wörter werden
        <xref alt="lemmatisiert" rid="glossary-lemmatisieren">lemmatisiert</xref>.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-reintext-version">Reintext-Version</styled-content></term>
      <def>
        <p>Die Reintext-Version ist die Version eines digitalen Textes
        oder einer Tabelle, in der keinerlei Formatierungen
        (Kursivierung, Metadatenauszeichnung etc.) enthalten sind.
        Reintext-Formate sind beispielsweise TXT, RTF und
        <xref alt="CSV" rid="glossary-csv">CSV</xref>.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-stoppwortliste">Stoppwortliste</styled-content></term>
      <def>
        <p>Stoppwörter sind hochfrequente Wörter, meist Funktionswörter,
        die, aufgrund ihrer grammatisch bedingten Häufigkeit,
        beispielsweise die Ergebnisse von inhaltlichen oder thematischen
        Analysen verzerren können. Deshalb werden diese Wörter,
        gesammelt in einer Stoppwortliste, bei digitalen Textanalysen
        meist nicht berücksichtigt.</p>
      </def>
    </def-item>
    <def-item>
      <term><styled-content id="glossary-type-token">Type/Token</styled-content></term>
      <def>
        <p>Das Begriffspaar „Type/Token“ wird grundsätzlich zur
        Unterscheidung von einzelnen Vorkommnissen (Token) und Typen
        (Types) von Wörtern oder Äußerungen in Texten genutzt. Ein Token
        ist also ein konkretes Exemplar eines bestimmten Typs, während
        ein Typ eine im Prinzip unbegrenzte Menge von Exemplaren (Token)
        umfasst.
        Es gibt allerdings etwas divergierende Definitionen zur
        Type-Token-Unterscheidung. Eine präzise Definition ist daher
        immer erstrebenswert. Der Satz „Ein Bär ist ein Bär.“ beinhaltet
        beispielsweise fünf Worttoken („Ein“, „Bär“, „ist“, „ein“,
        „Bär“) und drei Types, nämlich: „ein“, „Bär“, „ist“. Allerdings
        könnten auch vier Types, „Ein“, „ein“, „Bär“ und „ist“, als
        solche identifiziert werden, wenn Großbuchstaben beachtet
        werden.</p>
      </def>
    </def-item>
  </def-list>
</sec>
</body>
<back>
<ref-list>
  <title>Bibliographie</title>
  <ref id="ref-anacondasoftwaredistributionAnacondaDocumentation2020">
    <mixed-citation>Anaconda Software Distribution. 2020. Anaconda
    Documentation.
    <ext-link ext-link-type="uri" xlink:href="https://docs.anaconda.com">https://docs.anaconda.com</ext-link>.</mixed-citation>
  </ref>
  <ref id="ref-birdNaturalLanguageProcessing2009">
    <mixed-citation>Bird, Steven, Ewan Klein und Edward Loper. 2009.
    <italic>Natural language processing with Python: analyzing text with
    the natural language toolkit</italic>. O’Reilly
    Media.</mixed-citation>
  </ref>
  <ref id="ref-horstmannMethodenbeitragTopicModeling2018">
    <mixed-citation>Horstmann, Jan. 2024. Methodenbeitrag: Topic
    Modeling. Hg. von Evelyn Gius. <italic>forTEXT</italic> 1, Nr. 8.
    Topic Modeling (7. Oktober). doi:
    <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.48694/fortext.3717">10.48694/fortext.3717</ext-link>,
    <ext-link ext-link-type="uri" xlink:href="https://fortext.net/routinen/methoden/topic-modeling">https://fortext.net/routinen/methoden/topic-modeling</ext-link>.</mixed-citation>
  </ref>
  <ref id="ref-kluyverJupyterNotebooksPublishing2016">
    <mixed-citation>Kluyver, Thomas, Benjamin Ragan-Kelley, Fernando
    Pérez, Brian Granger, Matthias Bussonnier, Jonathan Frederic, Kyle
    Kelley, u. a. 2016. Jupyter Notebooks – a publishing format for
    reproducible computational workflows. In: <italic>Positioning and
    Power in Academic Publishing: Players, Agents and Agendas</italic>,
    hg. von F. Loizides und B. Schmidt, 87–90. IOS
    Press.</mixed-citation>
  </ref>
  <ref id="ref-schumacherLerneinheitNamedEntity2020">
    <mixed-citation>Schumacher, Mareike. 2024a. Lehrmodul: Named Entity
    Recognition mit Stanford NER lehren. Hg. von Evelyn Gius.
    <italic>forTEXT</italic> 1, Nr. 9. Named Entity Recognition (30.
    Oktober). doi:
    <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.48694/fortext.3768">10.48694/fortext.3768</ext-link>,
    <ext-link ext-link-type="uri" xlink:href="https://fortext.net/routinen/lehrmodule/named-entity-recognition-mit-stanford-ner-lehren">https://fortext.net/routinen/lehrmodule/named-entity-recognition-mit-stanford-ner-lehren</ext-link>.</mixed-citation>
  </ref>
  <ref id="ref-schumacherMethodenbeitragWord2vec2023">
    <mixed-citation>———. 2024c. Methodenbeitrag: word2vec. Hg. von
    Evelyn Gius. <italic>forTEXT</italic> 1, Nr. 10. word2vec (30.
    Oktober). doi:
    <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.48694/fortext.3815">10.48694/fortext.3815</ext-link>,
    <ext-link ext-link-type="uri" xlink:href="https://fortext.net/routinen/methoden/word2vec-1">https://fortext.net/routinen/methoden/word2vec-1</ext-link>.</mixed-citation>
  </ref>
  <ref id="ref-schumacherToolbeitragStanfordNamed2018">
    <mixed-citation>———. 2024b. Toolbeitrag: Stanford Named Entity
    Recognizer. Hg. von Evelyn Gius. <italic>forTEXT</italic> 1, Nr. 9.
    Named Entity Recognition (30. Oktober). doi:
    <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.48694/fortext.3767">10.48694/fortext.3767</ext-link>,
    <ext-link ext-link-type="uri" xlink:href="https://fortext.net/tools/tools/stanford-named-entity-recognizer">https://fortext.net/tools/tools/stanford-named-entity-recognizer</ext-link>.</mixed-citation>
  </ref>
</ref-list>
</back>
</article>
