Analyse 1: Diachrone Frequenzdiagramme #
Jetzt werden wir die CONLL-Daten nehmen und einige Analysen durchführen. Unser erster Schritt wird sein, die Wort-/Lemma-Häufigkeiten für die Monate des Jahres 1918 zu plotten und zu sehen, ob sie mit den Wellen der Grippepandemie korrelieren.
0. Importe und Daten-Upload #
Show code cell content
import pandas as pd
import re
from pathlib import Path
## for interactivity in jupyter books
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CustomJS, TextInput, Div, RadioButtonGroup
# Ensure Bokeh output is displayed in the notebook
output_notebook()
conllfiles = Path(r"../data/csv")
corpus_annotations = {}
for file in conllfiles.iterdir():
if file.suffix == '.csv':
#path = os.path.join(conllfiles, filename)
data = pd.read_csv(file)
corpus_annotations[file.name] = data
corpus_metadata = pd.read_csv(Path('../data/metadata/QUADRIGA_FS-Text-01_Data01_Corpus-Table.csv'), sep=';')
corpus_metadata = corpus_metadata.set_index('DC.identifier')
corpus_metadata
DC.publisher | DC.date | DC.source | |
---|---|---|---|
DC.identifier | |||
SNP2719372X-19180101-0-0-0-0 | Berliner Morgenpost | 1918-01-01 | https://content.staatsbibliothek-berlin.de/zef... |
SNP2719372X-19180102-0-0-0-0 | Berliner Morgenpost | 1918-01-02 | https://content.staatsbibliothek-berlin.de/zef... |
SNP2719372X-19180103-0-0-0-0 | Berliner Morgenpost | 1918-01-03 | https://content.staatsbibliothek-berlin.de/zef... |
SNP2719372X-19180104-0-0-0-0 | Berliner Morgenpost | 1918-01-04 | https://content.staatsbibliothek-berlin.de/zef... |
SNP2719372X-19180105-0-0-0-0 | Berliner Morgenpost | 1918-01-05 | https://content.staatsbibliothek-berlin.de/zef... |
... | ... | ... | ... |
SNP27112366-19191224-0-0-0-0 | Vossische Zeitung | 1919-12-24 | https://content.staatsbibliothek-berlin.de/zef... |
SNP27112366-19191227-0-0-0-0 | Vossische Zeitung | 1919-12-27 | https://content.staatsbibliothek-berlin.de/zef... |
SNP27112366-19191229-0-0-0-0 | Vossische Zeitung | 1919-12-29 | https://content.staatsbibliothek-berlin.de/zef... |
SNP27112366-19191230-0-0-0-0 | Vossische Zeitung | 1919-12-30 | https://content.staatsbibliothek-berlin.de/zef... |
SNP27112366-19191231-0-0-0-0 | Vossische Zeitung | 1919-12-31 | https://content.staatsbibliothek-berlin.de/zef... |
1328 rows × 3 columns
1. Suche nach einem Lemma und plotte die Häufigkeit #
class WordSearchEngine:
def __init__(self, corpus_annotated, corpus_metadata, granularity_parameter='month'):
self.granularity_parameter = granularity_parameter
self.prepare_index_dataframe_for_search(corpus_annotated, corpus_metadata)
def prepare_index_dataframe_for_search(self, corpus_annotated, corpus_metadata):
for filename, annotated_text in corpus_annotated.items():
txtname = filename.replace('.csv', '')
if txtname in corpus_metadata.index:
year, month, day, week, newspaper = self.get_date_and_newsp_from_fname(txtname, corpus_metadata)
annotated_text['month'] = month
annotated_text['day'] = day
annotated_text['week'] = week
annotated_text['newspaper'] = newspaper
self.full_df = pd.concat(corpus_annotated.values()) ## a df that contains all words in all newspapers
# for interactive plotting of relative freqs we'll need all these:
#self.monthly_word_counts = self.full_df.groupby('month').count().Token
#self.weekly_word_counts = self.full_df.groupby('week').count().Token
#self.daily_word_counts = self.full_df.groupby('day').count().Token
print(f'Searching in a corpus of {self.full_df.shape[0]} word occurences')
def get_date_and_newsp_from_fname(self, txtname, corpus_metadata):
date_and_newspaper = corpus_metadata.loc[txtname, ['DC.date', 'DC.publisher']]
date = date_and_newspaper.iloc[0]
newspaper = date_and_newspaper.iloc[1]
date_str = str(date)
year = date_str[:4]
month = f"{date_str[:7]}"
day = date_str
# week
date_obj = pd.to_datetime(date_str)
week_number = f'{year}_week_{date_obj.weekofyear}'
return year, month, day, week_number, newspaper
def search_and_plot(self, search_terms, absolute_freqs=True):
search_terms = search_terms.split(',')
search_terms = [x.strip() for x in search_terms]
result = self.full_df.query(f'Lemma.isin({search_terms})')
## count freqs by different time spans -- we'll need them all for the interactive graph
freqs_month = result.groupby('month').count().Lemma
grouped_by_week = result.groupby('week')
freqs_week = grouped_by_week.count().Lemma
week_dates = grouped_by_week.first()['day']
freqs_week.index = week_dates
freqs_week = freqs_week.sort_index()
freqs_day = result.groupby('day').count().Lemma
self.plot_with_js(freqs_month, freqs_week, freqs_day, search_terms)
def plot_with_js(self, freqs_month, freqs_week, freqs_day, words):
# Prepare data sources
daily_source = ColumnDataSource(data=dict(x=pd.to_datetime(freqs_day.index), y=list(freqs_day)))
weekly_source = ColumnDataSource(data=dict(x=pd.to_datetime(freqs_week.index), y=list(freqs_week)))
monthly_source = ColumnDataSource(data=dict(x=pd.to_datetime(freqs_month.index), y=list(freqs_month)))
starter_source = ColumnDataSource(data=dict(x=pd.to_datetime(freqs_month.index), y=list(freqs_month)))
#print('weeks x:\n', pd.to_datetime(freqs_week.index))
#print('weeks y:\n', list(freqs_week))
# Create a plot
p = figure(title=f"Frequency of words {words}", x_axis_type="datetime", x_axis_label='Time',
y_axis_label='Frequency', width=700, height=400)
line = p.line('x', 'y', source=starter_source, line_width=2, color='blue')
# Callback to update the data based on selected mode
callback = CustomJS(args=dict(line=line, daily_source=daily_source,
weekly_source=weekly_source, monthly_source=monthly_source),
code="""
const mode = cb_obj.active;
if (mode === 2) {
line.data_source.data = daily_source.data;
} else if (mode === 1) {
line.data_source.data = weekly_source.data;
} else if (mode === 0) {
line.data_source.data = monthly_source.data;
}
line.data_source.change.emit();
""")
# RadioButtonGroup to select mode
radio_button_group = RadioButtonGroup(labels=["Monthly", "Weekly", "Daily"], active=0)
radio_button_group.js_on_change('active', callback)
# Layout the RadioButtonGroup and plot
layout = column(radio_button_group, p)
show(layout)
search_terms = TextInput(value='Grippe, Krankheit',
title="Geben Sie die zu suchenden Wörter ein und trennen Sie sie durch Kommas, wenn es mehrere sind:") #input('Insert words to search, split by comma if more than one: ')
search_terms_str = search_terms.value.strip()
# JavaScript callback to update the in Jupyter Book
rewrite_var_after_input = CustomJS(args=dict(text_input=search_terms), code="""
var word = text_input.value.trim();
console.log('Input value:', word);
function sendToPython(){
var kernel = IPython.notebook.kernel;
kernel.execute("search_terms_str = '" + word + "'");
}
sendToPython();
""")
search_terms.js_on_change('value', rewrite_var_after_input)
# Layout and display
layout = column(search_terms)
show(layout)
engine = WordSearchEngine(corpus_annotations, corpus_metadata)
Searching in a corpus of 33192061 word occurences
engine.search_and_plot(search_terms_str)
3. Diskussion des Zwischenergebnisses#
Ist dieses Ergebnis sinnvoll und spiegelt es tatsächlich etwas wider? Eine Möglichkeit, dies zu überprüfen, besteht darin, unser Diagramm mit den tatsächlichen Daten über die Intensität der Pandemie zu vergleichen.
In (Taubenberger, J. K., & Morens, D. M. (2006). 1918 Influenza: the Mother of All Pandemics. Emerging Infectious Diseases, 12(1), 15-22. https://doi.org/10.3201/eid1201.050979) wird festgestellt, dass ‘The first pandemic influenza wave appeared in the spring of 1918, followed in rapid succession by much more fatal second and third waves in the fall and winter of 1918–1919, respectively’(‘Die erste Pandemie-Influenza-Welle im Frühjahr 1918 auftrat, gefolgt von weitaus tödlicheren zweiten und dritten Wellen im Herbst und Winter 1918–1919’). Sie ergänzen diese Aussage auch mit einem Diagramm aus einem früheren Papier (Jordan E. (1927). Epidemic influenza: a survey. Chicago: American Medical Association):
Unsere zwei Wellen von Erwähnungen des Wortes ‘Grippe’ scheinen den Sterblichkeitszahlen zu entsprechen, was darauf hindeuten könnte, dass die Methode, obwohl sehr einfach, funktioniert und dass historische Ereignisse manchmal in Wortfrequenzzählungen reflektiert werden können… Die dritte Welle scheint nicht reproduziert zu werden, was eine weitere Untersuchung erfordert. Eine Hypothese könnte sein, dass, ähnlich wie bei der COVID-Pandemie, neue Krankheitswellen irgendwann aufhören, die Aufmerksamkeit der Öffentlichkeit zu erregen. Beispielsweise waren die COVID-Wellen im Jahr 2021 stärker als die im Jahr 2020, aber die Berichterstattung in den Nachrichten nahm bereits ab. Dies könnte besonders für Anfang 1919 zutreffen, als nach dem Verlust des Krieges und der Revolution von 1918 Grippetodesfälle kein Nachrichtenthema mehr waren.