7.3. 🚀 Analyse 2: Keyword in Context (KWIC)#
Hinweise zur Ausführung des Notebooks
Dieses Notebook kann auf unterschiedlichen Levels erarbeitet werden (siehe Abschnitt “Technische Voraussetzungen”):
Book-Only Mode: Sie lesen das Notebook hier im “Jupyter Book”, ohne den Code selbst auszuführen.
Cloud Mode: Klicken Sie oben rechts in der Menüleiste auf das Raketen-Symbol 🚀 und wählen Sie “Colab”, um das Notebook auszuführen.
Local Mode: Klicken Sie oben rechts in der Menüleiste auf das Download-Symbol ↓ und wählen Sie “.ipynb”, um das Notebook lokal auszuführen.
7.3.1. Übersicht#
Im Folgenden werden die annotierten Dateien (CSV-Format) analysiert. Unser Ziel ist es, den annotierten Korpus zu nutzen, um KWIC-Ausgaben zu erzeugen.
Dafür werden folgende Schritte durchgeführt:
Einlesen des Korpus, der Metadaten und der Grippe-Wortliste
Extraktion und Darstellung der Wortkontexte durch KWIC
Informationen zum Ausführen des Notebooks – Zum Ausklappen klicken ⬇️
Voraussetzungen zur Ausführung des Jupyter Notebooks
- Installieren der Bibliotheken
- Pfad zu den Daten setzen
- Laden der Daten (s.u.)
Show code cell content
# 🚀 Install libraries
! pip install pandas bokeh
Show code cell content
import re
from pathlib import Path
import pandas as pd
from tqdm import tqdm
import requests
## for interactivity in jupyter books
from bokeh.io import output_notebook, show
from bokeh.layouts import column, layout
from bokeh.models import ColumnDataSource, DataTable, DateFormatter, TableColumn
# Ensure Bokeh output is displayed in the notebook
output_notebook()
Bevor wir Daten herunterladen, definieren wir eine kleine Hilfsfunktion download_file. Sie lädt eine Datei plattformunabhängig – also auch unter Windows – aus dem Internet in einen Zielordner herunter und ersetzt damit das Kommando wget, das nicht auf allen Systemen (z.B. Windows) nativ verfügbar ist.
# helper: download a single file (cross-platform replacement for `! wget -P`)
def download_file(url, target_dir):
"""Download the file at `url` into `target_dir`, keeping its original name."""
target_dir = Path(target_dir)
target_dir.mkdir(parents=True, exist_ok=True)
target_path = target_dir / url.split("/")[-1]
response = requests.get(url)
response.raise_for_status()
target_path.write_bytes(response.content)
return target_path
7.3.2. Einlesen der Daten, Metadaten#
Einlesen des Korpus (CSV-Dateien)#
Informationen zum Ausführen des Notebooks – Zum Ausklappen klicken ⬇️
Zuerst wird der Ordner angelegt, in dem die CSV-Dateien gespeichert werden. Der Einfachheit halber wird die gleiche Datenablagestruktur wie in dem GitHub Repository, in dem die Daten gespeichert sind, vorausgesetzt. Danach werden alle CSV-Dateien im Korpus heruntergeladen und gespeichert. Dafür sind folgende Schritte nötig:- Es wird eine Liste erstellt, die die URLs zu den einzelnen CSV-Dateien beinhaltet.
- Alle Dateien aus der Liste werden heruntergeladen und in dem Ordner ../data/csv gespeichert.
Show code cell content
# 🚀 Create data directory path
corpus_dir = Path("../data/csv")
if not corpus_dir.exists():
corpus_dir.mkdir(parents=True)
Show code cell content
# 🚀 Create download list
github_api_txt_dir_path = "https://api.github.com/repos/quadriga-dk/Text-Fallstudie-1/contents/data/csv"
txt_dir_info = requests.get(github_api_txt_dir_path).json()
url_list = [entry["download_url"] for entry in txt_dir_info]
Show code cell content
# ⚠️ Only execute, if you haven't downloaded the files yet!
# 🚀 Download all csv files – this step will take a while (ca. 7 minutes)
for url in tqdm(url_list, desc="Downloading csv files"):
download_file(url, "../data/csv")
Setzen des Pfads:
# set the path to csv files to be processed
csv_dir = Path(r"../data/csv")
# Create dictionary to save the corpus data (filenames and tables)
corpus_annotations = {}
# Iterate over csv files
for file in csv_dir.iterdir():
# check if the entry is a file, not a directory
if file.is_file():
# check if the file has the correct suffix csv
if file.suffix == '.csv':
# read the csv table to a data frame
data = pd.read_csv(file)
# save the data frame to the dictionary, key=filename (without suffix), value=dataframe
corpus_annotations[file.name] = data
Einlesen der Metadaten#
Informationen zum Ausführen des Notebooks – Zum Ausklappen klicken ⬇️
Zuerst wird der Ordner angelegt, in dem die Metadaten-Datei gespeichert wird. Wieder wird die gleiche Datenablagestruktur wie in dem GitHub Repository vorausgesetzt. Der Text wird aus GitHub heruntergeladen und in dem Ordner ../data/metadata/ abgespeichert. Der Pfad kann in der Variable metadata_path angepasst werden. Die einzulesende Datei muss die Endung `.csv` haben.Show code cell content
# 🚀 Create metadata directory path
metadata_dir = Path("../data/metadata")
if not metadata_dir.exists():
metadata_dir.mkdir()
Show code cell content
# 🚀 Load the metadata file from GitHub
download_file("https://raw.githubusercontent.com/quadriga-dk/Text-Fallstudie-1/refs/heads/main/data/metadata/QUADRIGA_FS-Text-01_Data01_Corpus-Table.csv", "../data/metadata")
# set path to metadata file
metadata_path = '../data/metadata/QUADRIGA_FS-Text-01_Data01_Corpus-Table.csv'
# read metadata file to pandas dataframe and set index
corpus_metadata = pd.read_csv(metadata_path, sep=';')
corpus_metadata = corpus_metadata.set_index('DC.identifier')
Kombinieren von tokenisierten Texten und deren Metadaten für KWIC-Suche#
def get_date_metadata(txtname, corpus_metadata):
date = corpus_metadata.loc[txtname, 'DC.date']
date = str(date)
year = date[:4]
month = date[:7]
day = date
return year, month, day
for filename, annotated_text in corpus_annotations.items():
txtname = filename.replace('.csv', '')
if txtname in corpus_metadata.index:
year, month, day = get_date_metadata(txtname, corpus_metadata)
annotated_text['month'] = month
annotated_text['filename'] = filename
search_df = pd.concat(corpus_annotations.values())
search_df = search_df.reset_index()
search_df["Token"] = search_df["Token"].astype(str)
print(f'The KWIC-search will be over a corpus of {search_df.shape[0]} word occurences')
The KWIC-search will be over a corpus of 33185650 word occurences
Einlesen der Wortliste (Semantisches Feld „Grippe“)#
Show code cell content
# 🚀 Create word list directory path
wordlist_dir = Path("../data/wordlist")
if not wordlist_dir.exists():
wordlist_dir.mkdir()
Show code cell content
# 🚀 Load the wordlist file from GitHub
download_file("https://raw.githubusercontent.com/quadriga-dk/Text-Fallstudie-1/refs/heads/main/data/wordlist/grippe.txt", "../data/wordlist")
path_to_wordlist = Path("../data/wordlist/grippe.txt")
word_list = path_to_wordlist.read_text(encoding="utf-8").split("\n")
Wie sieht die Wortliste aus?
word_list
['Influenza',
'Grippe',
'Grippeepidemie',
'Grippewelle',
'Grippekranke',
'Grippepandemie',
'Lungenentzündung',
'Krankheitswelle',
'Seuchenzug',
'Krankheitsausbruch',
'Fieberanfall',
'Schüttelfrost',
'Atemnot',
'Körpererschöpfung',
'Genesungszeit',
'Ansteckungsgefahr',
'Seuchenschutz',
'Desinfektionsmittel',
'Schutzmaske',
'Krankenstation',
'Isolationsstation',
'Sanitätsdienst',
'Krankheitsverlauf',
'Todesopfer',
'Krankheitssymptom',
'Erkrankungsfall',
'Lungeninfektion',
'']
7.3.3. Extraktion und Darstellung der Wortkontexte durch KWIC#
Show code cell content
class ContextViewer:
def __init__(self, search_df):
self.full_df = search_df
print(f'Searching in a corpus of {self.full_df.shape[0]} word occurences')
def show_kwic_output(self, search_terms, n_words):
contexts_df = self.get_context_words(search_terms, n_words)
# Convert DataFrame to ColumnDataSource
source = ColumnDataSource(contexts_df)
# Create Table Columns
columns = [TableColumn(field=col, title=col) for col in contexts_df.columns]
# Create DataTable
data_table = DataTable(source=source, columns=columns)
# Display DataTable
output_notebook() # Use this to render in Jupyter Notebook
show(layout([data_table]))
def get_context_words(self, search_terms, n_words):
#search_terms = input('Insert a word to search, split by comma if more than one: ')
if len(search_terms) == 0:
search_terms = word_list
if isinstance(search_terms, str):
search_terms = search_terms.split(',')
search_terms = [x.strip() for x in search_terms]
indices = self.full_df.query(f'Lemma.isin({search_terms})').index
#print(indices)
left_contexts = []
this_words = []
right_contexts = []
months = []
for indice in indices:
left = self.full_df.iloc[indice-n_words:indice-1, ]["Token"]
leftс = left[~left.str.contains('\n')]
right = self.full_df.iloc[indice+1:indice+n_words, ]["Token"]
rightс = right[~right.str.contains('\n')]
left_contexts.append(' '.join(leftс))
right_contexts.append(' '.join(rightс))
this_words.append(self.full_df.iloc[indice, ]["Token"])
months.append(self.full_df.iloc[indice, ]["month"])
newdf = pd.DataFrame()
newdf['left_context'] = left_contexts
newdf['word'] = this_words
newdf['right_context'] = right_contexts
newdf['month'] = months
return newdf
kwic = ContextViewer(search_df)
Searching in a corpus of 33185650 word occurences
Worteingabe für die Suche und KWIC-Output (für Cloud Mode und Local Mode)#
Show code cell content
text_input = input("Geben Sie die zu suchenden Wörter ein und trennen Sie sie durch Kommas, wenn es mehrere sind:")
# Convert the input to a list by splitting the input by comma
search_terms = [x.strip() for x in text_input.split(',')]
Show code cell content
kwic.show_kwic_output(search_terms, n_words=5)