import os
import gzip
import json
import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import re
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
BASIS_URL = 'https://www.parlament.gv.at'
#Plenarsitzungen des Nationalrats für eine gegebene Gesetzesperiode
LISTE_URL = '/PAKT/STPROT/index.shtml?SUCH=&xdocumentUri=%2FPAKT%2FSTPROT%2Findex.shtml&pageNumber=&R_PLSO=PL' + \
'&GP={gp}&STEP=&INTRANET=N&feldRnr=1&STPROT=ALLE&ascDesc=DESC&FBEZ=FP_011&NRBRBV=NR&BEZ=FP_211' + \
'&requestId=D6CBFB9744&LISTE=&jsMode=&listeId=211&NUR_VORL=N'
Falls schon heruntergeladene Protokolle existieren, diese laden.
%%time
FILE = 'protokolle_txt.json.zip'
if os.path.exists(FILE):
# Protokolle aus Datei laden
with gzip.open(FILE, 'rt') as f:
protokolle_txt = json.load(f)
else:
# Protokolle herunterladen
protokolle_txt = dict()
Wall time: 5.55 s
Hier werden Protokolle geladen, für angegebene Gesetzesperiode. Falls bestehende Protokolle schon geladen sind, nicht nötig auszuführen.
%%time
# Status 8.8.2016
# Stenographische Protokolle in strukturiertem HTML Format ab XXII. Gesetzgebungsperiode (23.05.2006, 150. NR Sitzung)
# Ab XXIII. Gesetzgebungsperiode (1. Sitzung 30.10.2006) durchgehend neues Format.
# Analysiere daher ab XXIII. Gesetzgebungsperiode
# Aktuellstest Protokoll: XXV. Gesetzgebungsperiode, 24.02.2016
gesetzgebungsperioden = ('XXV', 'XXIV', 'XXIII')
for gp in gesetzgebungsperioden:
print(' ')
print(gp)
# Internetseite mit Links zu den Protokollen der entsprechenden Gesetzgebungsperidoe wird abgerufen
r = requests.get(BASIS_URL + LISTE_URL.format(gp = gp))
soup = BeautifulSoup(r.text, 'lxml')
# Alle Links in der Ergebnistabelle
links = soup.find('table', class_='tabelle filter').find_all('a')
# Davon alle auf Stenographisches Protokoll in HTML Format
links = [link for link in links if link.text == 'HTML']
# Davon die URL
links = [link.get('href') for link in links]
for link in links:
# In der URL steckt die Nummer der Sitzung, der zur Information ausgegeben wird
print(link.split('/')[5].split('_')[1], end=' ')
# Eindeutiger key des Protokolls, bestehend aus Gesetzperiode, Art der Sitzung (Nationalrat) und Nummer
key = gp + '_' + link.split('/')[5]
r_temp = requests.get(BASIS_URL + link)
protokolle_txt[key] = r_temp.text
print()
# Protokolle in gezippten JSON File speichern
with gzip.open(FILE, mode="wt") as f:
json.dump(protokolle_txt, f)
XXV 00114 00113 00112 00111 00110 00109 00108 00107 00106 00105 00103 00102 00101 00100 00099 00098 00097 00096 00095 00094 00093 00092 00091 00090 00089 00088 00087 00086 00085 00084 00083 00082 00081 00080 00079 00078 00077 00076 00075 00074 00073 00072 00071 00070 00069 00068 00067 00066 00065 00064 00063 00062 00061 00060 00059 00058 00057 00056 00055 00054 00053 00052 00051 00050 00049 00048 00047 00046 00045 00044 00043 00042 00041 00040 00039 00038 00037 00036 00035 00034 00033 00032 00031 00030 00029 00028 00027 00026 00025 00024 00023 00022 00021 00020 00019 00018 00017 00016 00015 00014 00013 00012 00011 00010 00009 00008 00007 00006 00005 00004 00003 00002 00001 XXIV 00220 00219 00218 00217 00216 00215 00214 00213 00212 00211 00210 00209 00208 00207 00206 00205 00204 00203 00202 00201 00200 00199 00198 00197 00196 00195 00194 00193 00192 00191 00190 00189 00188 00187 00186 00185 00184 00183 00182 00181 00180 00179 00178 00177 00176 00175 00174 00173 00172 00171 00170 00169 00168 00167 00166 00165 00164 00163 00162 00161 00160 00159 00158 00157 00156 00155 00154 00153 00152 00151 00150 00149 00148 00147 00146 00145 00144 00143 00142 00141 00140 00139 00138 00137 00136 00135 00134 00133 00132 00131 00130 00129 00128 00127 00126 00125 00124 00123 00122 00121 00120 00119 00118 00117 00116 00115 00114 00113 00112 00111 00110 00109 00108 00107 00106 00105 00104 00103 00102 00101 00100 00099 00098 00097 00096 00095 00094 00093 00092 00091 00090 00089 00088 00087 00086 00085 00084 00083 00082 00081 00080 00079 00078 00077 00076 00075 00074 00073 00072 00071 00070 00069 00068 00067 00066 00065 00064 00063 00062 00061 00060 00059 00058 00057 00056 00055 00054 00053 00052 00051 00050 00049 00048 00047 00046 00045 00044 00043 00042 00041 00040 00039 00038 00037 00036 00035 00034 00033 00032 00031 00030 00029 00028 00027 00026 00025 00024 00023 00022 00021 00020 00019 00018 00017 00016 00015 00014 00013 00012 00011 00010 00009 00008 00007 00006 00005 00004 00003 00002 00001 XXIII 00076 00075 00074 00073 00072 00071 00070 00069 00068 00067 00066 00065 00064 00063 00062 00061 00060 00059 00058 00057 00056 00055 00054 00053 00052 00051 00050 00049 00048 00047 00046 00045 00044 00043 00042 00041 00040 00039 00038 00037 00036 00035 00034 00033 00032 00031 00030 00029 00028 00027 00026 00025 00024 00023 00022 00021 00020 00019 00018 00017 00016 00015 00014 00013 00012 00011 00010 00009 00008 00007 00006 00005 00004 00003 00002 00001 Wall time: 5min 30s
len(protokolle_txt)
409
Wir haben also 409 Nationalratssitzungen. Jeder der Sitzungen ist im HTML-Format gespeichert.
protokolle_txt['XXIII_NRSITZ_00043'][:400]
'<html>\r\n<head>\r\n<meta http-equiv=Content-Type content="text/html; charset=us-ascii">\r\n<meta name=Generator content="Microsoft Word 11 (filtered)">\r\n<title>Parlamentarische Materialien</title>\r\n<style>\r\n</style>\r\n<link rel=stylesheet type=text/css href="/PAKT/VHG/XXIII/NRSITZ/NRSITZ_00043/NRSP_043.css"><link rel="stylesheet" type="text/css" href="/styles/PDSteno.css"></head>\r\n<body lang=DE-AT>\r\n<di'
Falls die Protokolle schon ausgelsen wurden und strukturiert in einem Datenframe gespeichert wurden, wird die Datei nun eingelesen.
%%time
FILE = 'df_protokolle.pkl'
if os.path.exists(FILE):
# Protokolle aus Datei laden
df = pd.read_pickle(FILE)
Wall time: 375 ms
Hier werden Protokolle ausgelesen und ausgewählte Elemente in einen Datenframe gespeichert. Das dauert einige Zeit. Falls entsprechende Datenframe schon geladen ist und kein neues Parsen gewünscht wird, nicht ausführen.
%%time
# key_okay speichert alle Protokolle, die bereits ausgelesen wurden.
# Nun sollte das Auslesen in einem Lauf funktioneren. Während des Entwickeln des Codes,
# wurde der folgende Code öfters ausgeführt und ich wollte nicht jedesmal ganz von vorne anfangen.
key_okay=[]
# Ergebnis wird in einem Datenframe gespeichert
df = pd.DataFrame()
# Countdown damit man sieht, wie viele Protokolle noch ausgelesen werden müssen
countdown = len(protokolle_txt) - len(key_okay)
for key in protokolle_txt:
#for key in ('XXIV_NRSITZ_00207',):
if key in key_okay:
continue
countdown = countdown - 1
# HTML-Protokoll parsen mittels BeautifulSoup
txt = protokolle_txt[key]
soup = BeautifulSoup(txt, 'lxml')
# Bei manchen Sitzungen gibt es Fehler bei den IDs (Name, Datum, ...).
# Diese werden manuell überschrieben
if key == 'XXIV_NRSITZ_00026':
# Falsche IDs in entsprechendem Protokoll
sitzung = '26. Sitzung des\r\nNationalrates der Republik Österreich'
periode = 'XXIV. Gesetzgebungsperiode'
datum = 'Dienstag, 16. Juni 2009'
elif key == 'XXIII_NRSITZ_00060':
# Falsche IDs in entsprechendem Protokoll
sitzung = '60. Sitzung des\r\nNationalrates der Republik Österreich'
periode = 'XXIII. Gesetzgebungsperiode'
datum = 'Donnerstag, 8. Mai 2008'
# Normalerweise lassen sich die IDs auslesen, Identifikation anhand HTML-Class IDs
else:
sitzung = soup.find('p', class_='DBl02').get_text()
periode = soup.find('p', class_='DBl04').get_text()
datum = soup.find('p', class_='DBl05').get_text()
# Nochmals eine manuelle Datenbereinigung
if key == 'XXIV_NRSITZ_00220':
sitzung = '220. Sitzung des\r\nNationalrates der Republik Österreich'
if key == 'XXV_NRSITZ_00001':
datum = 'Dienstag, 29. Oktober 2013'
if key == 'XXIII_NRSITZ_00021':
datum = 'Donnerstag, 3. Mai 2007'
print(countdown, ' - ', key, ' - ', periode[:periode.find('.')], ' - ', sitzung[:sitzung.find('.')])
# Normalerweise sind Reden an HTML-Class 'StandardRB' (RB scheint für Rede-Beginn zu stehen) erkennbar
rede_pos = soup.find('p', class_='StandardRB')
while rede_pos != None:
# Nun wird der Text der Rede ausgelesen.
# Zuerst der Text des Paragraphs mit der 'StandardRB'-Class
rede_txt = rede_pos.get_text()
# Doch leider kann der Text über mehrere Paragraphen gehen.
# Zusätzlich Reden des Schriftführers/der Schriftführerin ausschließen, gibt es bei den Angelobungen neuer
# Abgeordneter, inklusive der Antworten "Ich gelobe."
# Hier gibt es oft Probleme mit den HTML-Classes, ebenso bei
while ((rede_txt.startswith('Schriftführer') == False) &
(max(rede_txt.find('Ich gelobe.'),rede_txt.find('Ich\r\ngelobe.')) == -1)):
# Identifikation der HTML Klasse des nächsten Paragraphs
rede_pos = rede_pos.find_next('p')
klasse = rede_pos['class']
# Paragraphen mit den folgenden Klassen sind eine Fortsetzung der Rede.
# Daher wird der Text zur bestehenden Rede hinzugefügt
if klasse in (['MsoNormal'], ['StandardRB'], ['MsoBodyText'], ['MsoListBullet'],
['INHANTR'],
['MsoListBulletCxSpFirst'], ['MsoListBulletCxSpMiddle'], ['MsoListBulletCxSpLast'],
['MsoBodyText2'], ['MsoNormalCxSpMiddle']) :
# INHANTR z.B. wegen XXII_NRSITZ_00058
# MsoListBulletCxSpFirst, ...Middle und ... Last z.B. wegen XXV_NRSITZ_00012
# MsoBodyText2 z.B wegen XXII_NRSITZ_00051, könnte man auch als Ende verwenden
# MsoNormalCxSpMiddle z.B. wegen XXIV_NRSITZ_00159
rede_txt = rede_txt + rede_pos.get_text()
# Die folgenden Klassen markieren das Ende einer Rede
elif klasse in (['StandardRE'], ['RE'], ['StandardR'], ['SB'], ['RE0']):
# RE0 z.B. wegen XXII_NRSITZ_00035
rede_txt = rede_txt + rede_pos.get_text()
df = df.append({'key':key, 'sitzung': sitzung, 'periode': periode, 'datum': datum, 'rede': rede_txt},
ignore_index=True)
break
# Die folgenden Klassen markieren einen Zwischentext, der nicht Teil der Rede ist
elif klasse in (['ZM'],['RB'], ['Format1']):
# 'ZM' - Entschließungsantrag
# 'RB' - Redebeginn, nicht benötigt, verwende StandardRB
pass
# Nicht oben erwähnte Klasse führt zu Fehlermeldung und speichert Dokument,
# damit es genauer analysiert werden kann.
# Wurde während der Entwicklung verwendet, sollte jetzt nicht vorkommen, es sei denn,
# es kommen neue Protokolle mit neuen Formatierungen vor
else:
print(key)
print(klasse)
print(rede_txt)
with open('temp.html', 'w', encoding='utf8') as fp:
fp.write(protokolle_txt[key])
raise ValueError('Unerwartetes Element in Rede')
# Finde Start der nächsten Rede
if key == 'XXIV_NRSITZ_00120':
# 'Falsches StandardR in entsprechendem Protokoll
rede_pos = rede_pos.find_next('p', class_=lambda x: x in ('StandardRB', 'StandardR'))
else:
rede_pos = rede_pos.find_next('p', class_='StandardRB')
key_okay.append(key)
df.to_pickle('df_protokolle.pkl')
408 - XXIII_NRSITZ_00028 - XXIII - 28 407 - XXIV_NRSITZ_00022 - XXIV - 22 406 - XXV_NRSITZ_00013 - XXV - 13 405 - XXIII_NRSITZ_00043 - XXIII - 43 404 - XXIV_NRSITZ_00065 - XXIV - 65 403 - XXIV_NRSITZ_00213 - XXIV - 213 402 - XXIII_NRSITZ_00018 - XXIII - 18 401 - XXIV_NRSITZ_00050 - XXIV - 50 400 - XXIV_NRSITZ_00146 - XXIV - 146 399 - XXIV_NRSITZ_00026 - XXIV - 26 398 - XXIV_NRSITZ_00205 - XXIV - 205 397 - XXV_NRSITZ_00083 - XXV - 83 396 - XXV_NRSITZ_00086 - XXV - 86 395 - XXIV_NRSITZ_00006 - XXIV - 6 394 - XXIII_NRSITZ_00036 - XXIII - 36 393 - XXIV_NRSITZ_00057 - XXIV - 57 392 - XXIII_NRSITZ_00008 - XXIII - 8 391 - XXIV_NRSITZ_00017 - XXIV - 17 390 - XXV_NRSITZ_00092 - XXV - 92 389 - XXIII_NRSITZ_00002 - XXIII - 2 388 - XXIV_NRSITZ_00049 - XXIV - 49 387 - XXIV_NRSITZ_00148 - XXIV - 148 386 - XXIV_NRSITZ_00158 - XXIV - 158 385 - XXIII_NRSITZ_00065 - XXIII - 65 384 - XXIV_NRSITZ_00089 - XXIV - 89 383 - XXIV_NRSITZ_00112 - XXIV - 112 382 - XXIV_NRSITZ_00087 - XXIV - 87 381 - XXIV_NRSITZ_00129 - XXIV - 129 380 - XXIII_NRSITZ_00039 - XXIII - 39 379 - XXIV_NRSITZ_00206 - XXIV - 206 378 - XXIV_NRSITZ_00115 - XXIV - 115 377 - XXIV_NRSITZ_00134 - XXIV - 134 376 - XXV_NRSITZ_00029 - XXV - 29 375 - XXIV_NRSITZ_00160 - XXIV - 160 374 - XXIV_NRSITZ_00010 - XXIV - 10 373 - XXIV_NRSITZ_00150 - XXIV - 150 372 - XXV_NRSITZ_00062 - XXV - 62 371 - XXV_NRSITZ_00068 - XXV - 68 370 - XXV_NRSITZ_00072 - XXV - 72 369 - XXIV_NRSITZ_00166 - XXIV - 166 368 - XXIII_NRSITZ_00009 - XXIII - 9 367 - XXV_NRSITZ_00004 - XXV - 4 366 - XXIV_NRSITZ_00183 - XXIV - 183 365 - XXV_NRSITZ_00020 - XXV - 20 364 - XXIV_NRSITZ_00153 - XXIV - 153 363 - XXV_NRSITZ_00090 - XXV - 90 362 - XXIII_NRSITZ_00054 - XXIII - 54 361 - XXIV_NRSITZ_00210 - XXIV - 210 360 - XXIV_NRSITZ_00123 - XXIV - 123 359 - XXIV_NRSITZ_00121 - XXIV - 121 358 - XXIII_NRSITZ_00056 - XXIII - 56 357 - XXIV_NRSITZ_00168 - XXIV - 168 356 - XXV_NRSITZ_00030 - XXV - 30 355 - XXIV_NRSITZ_00061 - XXIV - 61 354 - XXIV_NRSITZ_00078 - XXIV - 78 353 - XXIV_NRSITZ_00185 - XXIV - 185 352 - XXV_NRSITZ_00028 - XXV - 28 351 - XXV_NRSITZ_00089 - XXV - 89 350 - XXIII_NRSITZ_00031 - XXIII - 31 349 - XXIV_NRSITZ_00167 - XXIV - 167 348 - XXIV_NRSITZ_00131 - XXIV - 131 347 - XXV_NRSITZ_00034 - XXV - 34 346 - XXIV_NRSITZ_00119 - XXIV - 119 345 - XXV_NRSITZ_00063 - XXV - 63 344 - XXIV_NRSITZ_00218 - XXIV - 218 343 - XXV_NRSITZ_00026 - XXV - 26 342 - XXIV_NRSITZ_00203 - XXIV - 203 341 - XXV_NRSITZ_00056 - XXV - 56 340 - XXV_NRSITZ_00015 - XXV - 15 339 - XXIV_NRSITZ_00128 - XXIV - 128 338 - XXIV_NRSITZ_00099 - XXIV - 99 337 - XXIV_NRSITZ_00077 - XXIV - 77 336 - XXV_NRSITZ_00075 - XXV - 75 335 - XXIV_NRSITZ_00086 - XXIV - 86 334 - XXV_NRSITZ_00008 - XXV - 8 333 - XXIV_NRSITZ_00098 - XXIV - 98 332 - XXIV_NRSITZ_00052 - XXIV - 52 331 - XXIV_NRSITZ_00002 - XXIV - 2 330 - XXIII_NRSITZ_00012 - XXIII - 12 329 - XXIV_NRSITZ_00173 - XXIV - 173 328 - XXIII_NRSITZ_00076 - XXIII - des Nationalrates der Republik Österreic 327 - XXV_NRSITZ_00016 - XXV - 16 326 - XXIV_NRSITZ_00113 - XXIV - 113 325 - XXIII_NRSITZ_00006 - XXIII - 6 324 - XXIV_NRSITZ_00174 - XXIV - 174 323 - XXV_NRSITZ_00053 - XXV - 53 322 - XXV_NRSITZ_00010 - XXV - 10 321 - XXIV_NRSITZ_00195 - XXIV - 195 320 - XXV_NRSITZ_00102 - XXV - 102 319 - XXV_NRSITZ_00071 - XXV - 71 318 - XXIV_NRSITZ_00016 - XXIV - 16 317 - XXIII_NRSITZ_00023 - XXIII - 23 316 - XXIII_NRSITZ_00047 - XXIII - 47 315 - XXIV_NRSITZ_00176 - XXIV - 176 314 - XXIV_NRSITZ_00041 - XXIV - 41 313 - XXIV_NRSITZ_00093 - XXIV - 93 312 - XXIV_NRSITZ_00105 - XXIV - 105 311 - XXV_NRSITZ_00114 - XXV - 114 310 - XXV_NRSITZ_00081 - XXV - 81 309 - XXIV_NRSITZ_00151 - XXIV - 151 308 - XXIII_NRSITZ_00037 - XXIII - 37 307 - XXIV_NRSITZ_00091 - XXIV - 91 306 - XXV_NRSITZ_00103 - XXV - 103 305 - XXIV_NRSITZ_00198 - XXIV - 198 304 - XXV_NRSITZ_00049 - XXV - 49 303 - XXIV_NRSITZ_00097 - XXIV - 97 302 - XXIV_NRSITZ_00186 - XXIV - 186 301 - XXIII_NRSITZ_00067 - XXIII - 67 300 - XXV_NRSITZ_00039 - XXV - 39 299 - XXIII_NRSITZ_00034 - XXIII - 34 298 - XXIV_NRSITZ_00062 - XXIV - 62 297 - XXIV_NRSITZ_00154 - XXIV - 154 296 - XXV_NRSITZ_00101 - XXV - 101 295 - XXIV_NRSITZ_00124 - XXIV - 124 294 - XXIV_NRSITZ_00048 - XXIV - 48 293 - XXIII_NRSITZ_00038 - XXIII - 38 292 - XXIV_NRSITZ_00144 - XXIV - 144 291 - XXV_NRSITZ_00031 - XXV - 31 290 - XXV_NRSITZ_00012 - XXV - 12 289 - XXIV_NRSITZ_00133 - XXIV - 133 288 - XXV_NRSITZ_00100 - XXV - 100 287 - XXIV_NRSITZ_00059 - XXIV - 59 286 - XXIV_NRSITZ_00207 - XXIV - 207 285 - XXV_NRSITZ_00058 - XXV - 58 284 - XXIII_NRSITZ_00058 - XXIII - 58 283 - XXIII_NRSITZ_00011 - XXIII - 11 282 - XXIV_NRSITZ_00007 - XXIV - 7 281 - XXIII_NRSITZ_00004 - XXIII - 4 280 - XXIV_NRSITZ_00019 - XXIV - 19 279 - XXIV_NRSITZ_00092 - XXIV - 92 278 - XXIV_NRSITZ_00032 - XXIV - 32 277 - XXIV_NRSITZ_00051 - XXIV - 51 276 - XXV_NRSITZ_00035 - XXV - 35 275 - XXIV_NRSITZ_00042 - XXIV - 42 274 - XXIII_NRSITZ_00073 - XXIII - 73 273 - XXV_NRSITZ_00065 - XXV - 65 272 - XXV_NRSITZ_00011 - XXV - 11 271 - XXIV_NRSITZ_00216 - XXIV - 216 270 - XXIV_NRSITZ_00125 - XXIV - 125 269 - XXIV_NRSITZ_00054 - XXIV - 54 268 - XXIV_NRSITZ_00040 - XXIV - 40 267 - XXV_NRSITZ_00021 - XXV - 21 266 - XXIV_NRSITZ_00108 - XXIV - 108 265 - XXIII_NRSITZ_00021 - XXIII - 21 264 - XXIV_NRSITZ_00075 - XXIV - 75 263 - XXIV_NRSITZ_00136 - XXIV - 136 262 - XXIV_NRSITZ_00214 - XXIV - 214 261 - XXV_NRSITZ_00073 - XXV - 73 260 - XXIV_NRSITZ_00101 - XXIV - 101 259 - XXV_NRSITZ_00066 - XXV - 66 258 - XXIII_NRSITZ_00074 - XXIII - 74 257 - XXIV_NRSITZ_00191 - XXIV - 191 256 - XXIV_NRSITZ_00056 - XXIV - 56 255 - XXIV_NRSITZ_00135 - XXIV - 135 254 - XXIV_NRSITZ_00127 - XXIV - 127 253 - XXIV_NRSITZ_00072 - XXIV - 72 252 - XXIV_NRSITZ_00178 - XXIV - 178 251 - XXIV_NRSITZ_00031 - XXIV - 31 250 - XXIV_NRSITZ_00140 - XXIV - 140 249 - XXIV_NRSITZ_00090 - XXIV - 90 248 - XXIV_NRSITZ_00094 - XXIV - 94 247 - XXV_NRSITZ_00085 - XXV - 85 246 - XXV_NRSITZ_00064 - XXV - 64 245 - XXIV_NRSITZ_00149 - XXIV - 149 244 - XXIV_NRSITZ_00155 - XXIV - 155 243 - XXV_NRSITZ_00097 - XXV - 97 242 - XXIV_NRSITZ_00044 - XXIV - 44 241 - XXIII_NRSITZ_00060 - XXIII - 60 240 - XXIV_NRSITZ_00085 - XXIV - 85 239 - XXIV_NRSITZ_00096 - XXIV - 96 238 - XXIII_NRSITZ_00042 - XXIII - 42 237 - XXIII_NRSITZ_00044 - XXIII - 44 236 - XXIV_NRSITZ_00015 - XXIV - 15 235 - XXIV_NRSITZ_00212 - XXIV - 212 234 - XXV_NRSITZ_00070 - XXV - 70 233 - XXV_NRSITZ_00002 - XXV - 2 232 - XXIV_NRSITZ_00028 - XXIV - 28 231 - XXIV_NRSITZ_00172 - XXIV - 172 230 - XXV_NRSITZ_00094 - XXV - 94 229 - XXIV_NRSITZ_00194 - XXIV - 194 228 - XXIV_NRSITZ_00008 - XXIV - 8 227 - XXIII_NRSITZ_00030 - XXIII - 30 226 - XXIV_NRSITZ_00021 - XXIV - 21 225 - XXIV_NRSITZ_00147 - XXIV - 147 224 - XXIV_NRSITZ_00159 - XXIV - 159 223 - XXIII_NRSITZ_00075 - XXIII - 75 222 - XXV_NRSITZ_00027 - XXV - 27 221 - XXV_NRSITZ_00057 - XXV - 57 220 - XXV_NRSITZ_00042 - XXV - 42 219 - XXIV_NRSITZ_00037 - XXIV - 37 218 - XXV_NRSITZ_00022 - XXV - 22 217 - XXV_NRSITZ_00088 - XXV - 88 216 - XXIII_NRSITZ_00072 - XXIII - 72 215 - XXV_NRSITZ_00014 - XXV - 14 214 - XXIV_NRSITZ_00169 - XXIV - 169 213 - XXV_NRSITZ_00038 - XXV - 38 212 - XXV_NRSITZ_00051 - XXV - 51 211 - XXIV_NRSITZ_00152 - XXIV - 152 210 - XXIV_NRSITZ_00163 - XXIV - 163 209 - XXV_NRSITZ_00047 - XXV - 47 208 - XXIII_NRSITZ_00017 - XXIII - 17 207 - XXV_NRSITZ_00082 - XXV - 82 206 - XXV_NRSITZ_00001 - XXV - 1 205 - XXV_NRSITZ_00040 - XXV - 40 204 - XXIV_NRSITZ_00003 - XXIV - 3 203 - XXIV_NRSITZ_00064 - XXIV - 64 202 - XXIV_NRSITZ_00118 - XXIV - 118 201 - XXIV_NRSITZ_00012 - XXIV - 12 200 - XXIV_NRSITZ_00179 - XXIV - 179 199 - XXIII_NRSITZ_00010 - XXIII - 10 198 - XXV_NRSITZ_00006 - XXV - 6 197 - XXIV_NRSITZ_00197 - XXIV - 197 196 - XXIV_NRSITZ_00164 - XXIV - 164 195 - XXIV_NRSITZ_00080 - XXIV - 80 194 - XXV_NRSITZ_00017 - XXV - 17 193 - XXIV_NRSITZ_00130 - XXIV - 130 192 - XXIII_NRSITZ_00014 - XXIII - 14 191 - XXIV_NRSITZ_00180 - XXIV - 180 190 - XXIV_NRSITZ_00060 - XXIV - 60 189 - XXIV_NRSITZ_00181 - XXIV - 181 188 - XXIV_NRSITZ_00114 - XXIV - 114 187 - XXIV_NRSITZ_00211 - XXIV - 211 186 - XXIV_NRSITZ_00209 - XXIV - 209 185 - XXIII_NRSITZ_00033 - XXIII - 33 184 - XXV_NRSITZ_00018 - XXV - 18 183 - XXV_NRSITZ_00074 - XXV - 74 182 - XXIV_NRSITZ_00116 - XXIV - 116 181 - XXV_NRSITZ_00037 - XXV - 37 180 - XXIII_NRSITZ_00013 - XXIII - 13 179 - XXIV_NRSITZ_00013 - XXIV - 13 178 - XXV_NRSITZ_00098 - XXV - 98 177 - XXIV_NRSITZ_00177 - XXIV - 177 176 - XXV_NRSITZ_00009 - XXV - 9 175 - XXIV_NRSITZ_00202 - XXIV - 202 174 - XXIV_NRSITZ_00046 - XXIV - 46 173 - XXV_NRSITZ_00109 - XXV - 109 172 - XXIV_NRSITZ_00142 - XXIV - 142 171 - XXIII_NRSITZ_00057 - XXIII - 57 170 - XXIV_NRSITZ_00055 - XXIV - 55 169 - XXIV_NRSITZ_00170 - XXIV - 170 168 - XXIV_NRSITZ_00043 - XXIV - 43 167 - XXV_NRSITZ_00080 - XXV - 80 166 - XXV_NRSITZ_00033 - XXV - 33 165 - XXIV_NRSITZ_00068 - XXIV - 68 164 - XXIV_NRSITZ_00157 - XXIV - 157 163 - XXIII_NRSITZ_00019 - XXIII - 19 162 - XXV_NRSITZ_00003 - XXV - 3 161 - XXIV_NRSITZ_00084 - XXIV - 84 160 - XXV_NRSITZ_00045 - XXV - 45 159 - XXIII_NRSITZ_00063 - XXIII - 63 158 - XXIII_NRSITZ_00022 - XXIII - 22 157 - XXV_NRSITZ_00087 - XXV - 87 156 - XXIII_NRSITZ_00066 - XXIII - 66 155 - XXIV_NRSITZ_00030 - XXIV - 30 154 - XXIII_NRSITZ_00027 - XXIII - 27 153 - XXV_NRSITZ_00111 - XXV - 111 152 - XXIV_NRSITZ_00208 - XXIV - 208 151 - XXIV_NRSITZ_00071 - XXIV - 71 150 - XXV_NRSITZ_00023 - XXV - 23 149 - XXIV_NRSITZ_00162 - XXIV - 162 148 - XXIV_NRSITZ_00182 - XXIV - 182 147 - XXIV_NRSITZ_00045 - XXIV - 45 146 - XXIV_NRSITZ_00193 - XXIV - 193 145 - XXIV_NRSITZ_00161 - XXIV - 161 144 - XXIV_NRSITZ_00029 - XXIV - 29 143 - XXIV_NRSITZ_00139 - XXIV - 139 142 - XXV_NRSITZ_00055 - XXV - 55 141 - XXV_NRSITZ_00061 - XXV - 61 140 - XXV_NRSITZ_00024 - XXV - 24 139 - XXIV_NRSITZ_00053 - XXIV - 53 138 - XXIII_NRSITZ_00062 - XXIII - 62 137 - XXIII_NRSITZ_00061 - XXIII - 61 136 - XXV_NRSITZ_00032 - XXV - 32 135 - XXV_NRSITZ_00113 - XXV - 113 134 - XXIII_NRSITZ_00020 - XXIII - 20 133 - XXIII_NRSITZ_00029 - XXIII - 29 132 - XXV_NRSITZ_00079 - XXV - 79 131 - XXIV_NRSITZ_00024 - XXIV - 24 130 - XXIV_NRSITZ_00156 - XXIV - 156 129 - XXIV_NRSITZ_00023 - XXIV - 23 128 - XXIII_NRSITZ_00059 - XXIII - 59 127 - XXIV_NRSITZ_00199 - XXIV - 199 126 - XXIV_NRSITZ_00188 - XXIV - 188 125 - XXIII_NRSITZ_00035 - XXIII - 35 124 - XXIV_NRSITZ_00034 - XXIV - 34 123 - XXIV_NRSITZ_00088 - XXIV - 88 122 - XXIV_NRSITZ_00165 - XXIV - 165 121 - XXIII_NRSITZ_00053 - XXIII - 53 120 - XXIV_NRSITZ_00095 - XXIV - 95 119 - XXIII_NRSITZ_00024 - XXIII - 24 118 - XXIII_NRSITZ_00068 - XXIII - 68 117 - XXIV_NRSITZ_00200 - XXIV - 200 116 - XXV_NRSITZ_00007 - XXV - 7 115 - XXV_NRSITZ_00036 - XXV - 36 114 - XXIV_NRSITZ_00103 - XXIV - 103 113 - XXIV_NRSITZ_00004 - XXIV - 4 112 - XXIV_NRSITZ_00027 - XXIV - 27 111 - XXIII_NRSITZ_00026 - XXIII - 26 110 - XXIV_NRSITZ_00035 - XXIV - 35 109 - XXIV_NRSITZ_00137 - XXIV - 137 108 - XXIV_NRSITZ_00070 - XXIV - 70 107 - XXIII_NRSITZ_00055 - XXIII - 55 106 - XXIII_NRSITZ_00025 - XXIII - 25 105 - XXIV_NRSITZ_00215 - XXIV - 215 104 - XXIV_NRSITZ_00025 - XXIV - 25 103 - XXV_NRSITZ_00043 - XXV - 43 102 - XXIII_NRSITZ_00049 - XXIII - 49 101 - XXIV_NRSITZ_00106 - XXIV - 106 100 - XXIV_NRSITZ_00145 - XXIV - 145 99 - XXIII_NRSITZ_00046 - XXIII - 46 98 - XXV_NRSITZ_00044 - XXV - 44 97 - XXIV_NRSITZ_00005 - XXIV - 5 96 - XXV_NRSITZ_00048 - XXV - 48 95 - XXV_NRSITZ_00019 - XXV - 19 94 - XXIII_NRSITZ_00071 - XXIII - 71 93 - XXIV_NRSITZ_00192 - XXIV - 192 92 - XXIV_NRSITZ_00009 - XXIV - 9 91 - XXIV_NRSITZ_00100 - XXIV - 100 90 - XXV_NRSITZ_00093 - XXV - 93 89 - XXIII_NRSITZ_00005 - XXIII - 5 88 - XXIV_NRSITZ_00141 - XXIV - 141 87 - XXIV_NRSITZ_00109 - XXIV - 109 86 - XXIV_NRSITZ_00102 - XXIV - 102 85 - XXIV_NRSITZ_00069 - XXIV - 69 84 - XXV_NRSITZ_00099 - XXV - 99 83 - XXIV_NRSITZ_00143 - XXIV - 143 82 - XXV_NRSITZ_00067 - XXV - 67 81 - XXIII_NRSITZ_00045 - XXIII - 45 80 - XXIV_NRSITZ_00001 - XXIV - 1 79 - XXIV_NRSITZ_00138 - XXIV - 138 78 - XXV_NRSITZ_00041 - XXV - 41 77 - XXV_NRSITZ_00096 - XXV - 96 76 - XXIV_NRSITZ_00079 - XXIV - 79 75 - XXV_NRSITZ_00025 - XXV - 25 74 - XXIV_NRSITZ_00033 - XXIV - 33 73 - XXV_NRSITZ_00091 - XXV - 91 72 - XXV_NRSITZ_00108 - XXV - 108 71 - XXIV_NRSITZ_00047 - XXIV - 47 70 - XXIII_NRSITZ_00051 - XXIII - 51 69 - XXIV_NRSITZ_00104 - XXIV - 104 68 - XXV_NRSITZ_00059 - XXV - 59 67 - XXIII_NRSITZ_00064 - XXIII - 64 66 - XXIV_NRSITZ_00117 - XXIV - 117 65 - XXV_NRSITZ_00005 - XXV - 5 64 - XXIV_NRSITZ_00063 - XXIV - 63 63 - XXIV_NRSITZ_00126 - XXIV - 126 62 - XXIV_NRSITZ_00196 - XXIV - 196 61 - XXV_NRSITZ_00077 - XXV - 77 60 - XXIV_NRSITZ_00020 - XXIV - 20 59 - XXIV_NRSITZ_00067 - XXIV - 67 58 - XXIV_NRSITZ_00132 - XXIV - 132 57 - XXIII_NRSITZ_00052 - XXIII - 52 56 - XXIV_NRSITZ_00066 - XXIV - 66 55 - XXIV_NRSITZ_00082 - XXIV - 82 54 - XXIV_NRSITZ_00014 - XXIV - 14 53 - XXIV_NRSITZ_00120 - XXIV - 120 52 - XXIII_NRSITZ_00050 - XXIII - 50 51 - XXIII_NRSITZ_00040 - XXIII - 40 50 - XXIII_NRSITZ_00001 - XXIII - 1 49 - XXV_NRSITZ_00107 - XXV - 107 48 - XXV_NRSITZ_00069 - XXV - 69 47 - XXIII_NRSITZ_00016 - XXIII - 16 46 - XXIV_NRSITZ_00189 - XXIV - 189 45 - XXIV_NRSITZ_00111 - XXIV - 111 44 - XXIV_NRSITZ_00184 - XXIV - 184 43 - XXV_NRSITZ_00084 - XXV - 84 42 - XXIV_NRSITZ_00219 - XXIV - 219 41 - XXIV_NRSITZ_00217 - XXIV - 217 40 - XXV_NRSITZ_00078 - XXV - 78 39 - XXIII_NRSITZ_00003 - XXIII - 3 38 - XXIV_NRSITZ_00220 - XXIV - 220 37 - XXV_NRSITZ_00105 - XXV - 105 36 - XXIII_NRSITZ_00041 - XXIII - 41 35 - XXV_NRSITZ_00054 - XXV - 54 34 - XXV_NRSITZ_00050 - XXV - 50 33 - XXIV_NRSITZ_00122 - XXIV - 122 32 - XXV_NRSITZ_00060 - XXV - 60 31 - XXIII_NRSITZ_00007 - XXIII - 7 30 - XXV_NRSITZ_00046 - XXV - 46 29 - XXV_NRSITZ_00095 - XXV - 95 28 - XXIV_NRSITZ_00074 - XXIV - 74 27 - XXIII_NRSITZ_00070 - XXIII - 70 26 - XXIV_NRSITZ_00187 - XXIV - 187 25 - XXIV_NRSITZ_00073 - XXIV - 73 24 - XXIV_NRSITZ_00171 - XXIV - 171 23 - XXIV_NRSITZ_00081 - XXIV - 81 22 - XXV_NRSITZ_00076 - XXV - 76 21 - XXIV_NRSITZ_00076 - XXIV - 76 20 - XXIV_NRSITZ_00110 - XXIV - 110 19 - XXIV_NRSITZ_00083 - XXIV - 83 18 - XXIV_NRSITZ_00058 - XXIV - 58 17 - XXIV_NRSITZ_00190 - XXIV - 190 16 - XXIV_NRSITZ_00011 - XXIV - 11 15 - XXIV_NRSITZ_00036 - XXIV - 36 14 - XXIV_NRSITZ_00018 - XXIV - 18 13 - XXIV_NRSITZ_00038 - XXIV - 38 12 - XXIV_NRSITZ_00039 - XXIV - 39 11 - XXIV_NRSITZ_00204 - XXIV - 204 10 - XXIII_NRSITZ_00069 - XXIII - 69 9 - XXV_NRSITZ_00052 - XXV - 52 8 - XXIV_NRSITZ_00201 - XXIV - 201 7 - XXIII_NRSITZ_00032 - XXIII - 32 6 - XXV_NRSITZ_00106 - XXV - 106 5 - XXV_NRSITZ_00112 - XXV - 112 4 - XXIII_NRSITZ_00015 - XXIII - 15 3 - XXV_NRSITZ_00110 - XXV - 110 2 - XXIII_NRSITZ_00048 - XXIII - 48 1 - XXIV_NRSITZ_00107 - XXIV - 107 0 - XXIV_NRSITZ_00175 - XXIV - 175 Wall time: 5min 5s
Die Sitzung XXIII_NRSITZ_00076 oben ist keine echte Sitzung, deshalb oben keine richtige Nummer. Spielt haber keine Rolle, da diese Sitzung eh keine Rede enthält.
Die folgenden drei Zellen wurden verwendet, um während der Entwicklung des Codes für einzelne Protokolle das entsprechende HTML File zu schreiben. Dieses konnte dann im Browser analysiert werden.
#print(key)
#with open('temp.html', 'w', encoding='utf8') as fp:
# fp.write(protokolle_txt[key])
#with open('temp.html', 'w', encoding='utf8') as fp:
# fp.write(protokolle_txt['XXIII_NRSITZ_00021'])
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 30820 entries, 0 to 30819 Data columns (total 5 columns): datum 30820 non-null object key 30820 non-null object periode 30820 non-null object rede 30820 non-null object sitzung 30820 non-null object dtypes: object(5) memory usage: 1.2+ MB
Wir haben also mehr als 30.000 Reden. So sehen die einzelnen Zeilen aus, pro Zeile gibt es eine Rede.
df[:3]
datum | key | periode | rede | sitzung | |
---|---|---|---|---|---|
0 | Donnerstag, 5. Juli 2007 | XXIII_NRSITZ_00028 | XXIII. Gesetzgebungsperiode | Abgeordneter\r\nDr. Peter Pilz (Grüne): Frau\r... | 28. Sitzung des\r\nNationalrates der Republik ... |
1 | Donnerstag, 5. Juli 2007 | XXIII_NRSITZ_00028 | XXIII. Gesetzgebungsperiode | Abgeordneter\r\nDr. Günther Kräuter (SPÖ):\r\n... | 28. Sitzung des\r\nNationalrates der Republik ... |
2 | Donnerstag, 5. Juli 2007 | XXIII_NRSITZ_00028 | XXIII. Gesetzgebungsperiode | Abgeordneter\r\nHeinz-Christian Strache (FPÖ):... | 28. Sitzung des\r\nNationalrates der Republik ... |
# Die Spalte periode wird verkürzt, nur der Wert, nicht noch der Text 'Gesetzgebungsperiode'
df.periode = df.periode.str.split('.',expand=True)[0]
Nun wollen wir das Datum bereinigen. Leider gibt es hier ein paar Sonderfälle, nämlich Sitzungen über mehrere Tage. Wir nehmen hier einfach den letzten Tag. Im Beispiel also den 29. Mai 2009.
df.loc[df.key=='XXIV_NRSITZ_00023', 'datum'].iloc[0]
'Mittwoch, 20., Dienstag, 26., Mittwoch, 27.,\r\nDonnerstag, 28., und Freitag, 29. Mai 2009'
df.datum = df.datum.str.rsplit(',', expand=True, n=1)[1].str.strip()
df.loc[df.key=='XXIV_NRSITZ_00023', 'datum'].iloc[0]
'29. Mai 2009'
Nun wird das Textformat, z.B. '29. Mai 2009' in ein Python-Datumsformat umgewandelt.
# Interessanterweise gibt es sowohl Februar als auch Feber
map_monat = {'Jänner':1, 'Feber':2, 'Februar':2, 'März':3, 'April':4, 'Mai':5, 'Juni':6, 'Juli':7, 'August':8,
'September':9, 'Oktober':10, 'November':11, 'Dezember':12}
def datum_umwandeln(txt):
txt = txt.replace('\r\n',' ').replace('\xa0', ' ')
tag, monat, jahr = txt.split(' ',maxsplit=2)
datum = tag + str(map_monat[monat]) + '.' + str(jahr)
return pd.to_datetime(datum, format='%d.%m.%Y')
df.datum = df.datum.apply(datum_umwandeln)
df.groupby(df.datum.dt.year)[['key']].count()
key | |
---|---|
datum | |
2006 | 357 |
2007 | 3158 |
2008 | 2763 |
2009 | 4319 |
2010 | 3417 |
2011 | 3629 |
2012 | 3273 |
2013 | 2888 |
2014 | 3506 |
2015 | 3139 |
2016 | 371 |
sns.set(context='talk', style='whitegrid')
sns.countplot(y=df.datum.dt.year, data=df)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden pro Jahr')
sns.set(font_scale=1)
sns.axlabel('Reden', 'Jahr')
sns.plt.savefig('reden_pro_jahr.svg')
sns.set(context='talk', style='whitegrid')
sns.countplot(y=df.datum.dt.month, data=df)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden pro Monat')
sns.set(font_scale=1)
sns.axlabel('Reden', 'Monat')
sns.plt.savefig('reden_pro_monat.svg')
sns.set(context='talk', style='whitegrid')
ax = sns.countplot(y=df.datum.dt.dayofweek, data=df)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden pro Wochentag')
sns.set(font_scale=1)
sns.axlabel('Reden', 'Wochentag')
#labels = [item.get_text() for item in ax.get_yticklabels()]
labels = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
ax.set_yticklabels(labels)
sns.plt.savefig('reden_pro_wochentag.svg')
df_temp = (df.groupby([df.datum.dt.year, df.datum.dt.month])['key'].count()).unstack()
mask = df_temp.isnull()
df_temp = df_temp.fillna(value=0)
df_temp = df_temp.astype('int')
df_temp[:3]
datum | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
datum | ||||||||||||
2006 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 43 | 159 | 155 |
2007 | 224 | 0 | 411 | 106 | 457 | 306 | 418 | 0 | 173 | 242 | 254 | 567 |
2008 | 407 | 0 | 325 | 266 | 297 | 402 | 476 | 0 | 238 | 67 | 33 | 252 |
sns.set(context='talk', style='whitegrid')
sns.heatmap(df_temp, annot=True, linewidths=.5, fmt='d', mask=mask)
#sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden (in 100 Reden)')
sns.set(font_scale=1)
sns.axlabel('Monat', 'Jahr')
sns.plt.savefig('reden_pro_jahr_monat.svg')
df_temp = (df.groupby([df.datum.dt.dayofweek, df.datum.dt.year])['key'].count()).unstack()
df_temp.index = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
mask = df_temp.isnull()
df_temp = df_temp.fillna(value=0)
df_temp = df_temp.astype('int')
df_temp[:3]
datum | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|---|---|---|---|---|---|---|
Mo | 43 | 0 | 70 | 0 | 0 | 0 | 21 | 29 | 196 | 49 | 0 |
Di | 0 | 381 | 387 | 585 | 219 | 725 | 470 | 289 | 733 | 241 | 0 |
Mi | 133 | 936 | 731 | 981 | 1746 | 981 | 1102 | 810 | 1275 | 1647 | 170 |
sns.set(context='talk', style='whitegrid')
sns.heatmap(df_temp, annot=True, linewidths=.5, fmt='d', mask=mask)
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden (in 100 Reden)')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Wochentag')
sns.plt.savefig('reden_pro_wochentag_jahr.svg')
df_temp = (df.groupby([df.datum.dt.dayofweek, df.datum.dt.month])['key'].count()).unstack()
df_temp.index = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
mask = df_temp.isnull()
df_temp = df_temp.fillna(value=0)
df_temp = df_temp.astype('int')
df_temp[:3]
datum | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Mo | 0 | 196 | 39 | 29 | 21 | 28 | 0 | 0 | 0 | 95 | 0 | 0 |
Di | 97 | 223 | 434 | 463 | 560 | 306 | 466 | 0 | 261 | 292 | 492 | 436 |
Mi | 922 | 653 | 885 | 756 | 910 | 974 | 1200 | 36 | 788 | 839 | 941 | 1608 |
sns.set(context='talk', style='whitegrid')
sns.heatmap(df_temp, annot=True, linewidths=.5, fmt='d', mask=mask)
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden (in 100 Reden)')
sns.set(font_scale=1)
sns.axlabel('Monat', 'Wochentag')
sns.plt.savefig('reden_pro_wochentag_monat.svg')
Der Redner ist der erste Teil des Felds rede. Dieser soll herausgelöst und extra gespeichert werden, inklusive der Partei.
#Sonderzeichen entfernen
df.rede = df.rede.str.replace('\xa0',' ')
df.rede = df.rede.str.replace('\r\n',' ')
df.rede = df.rede.str.replace('\xad','')
df.rede = df.rede.str.replace('†', '')
df.rede = df.rede.str.replace('|', '')
Sonderfall, erster Abschnitt der Rede fehlt, falsch in HTML abgebildet. Manuelle Korrektur.
mask = df.rede.str.startswith('Im Sicherheitsbereich bin ich zuständig')
rede_temp = df[mask].iloc[0].rede
rede_fehlend = '''Bundesministerin für Inneres Mag. Dr. Maria Theresia Fekter: Herr Präsident! Hohes Haus!
Werte Damen und Herren auf der Besuchergalerie und vor den Bildschirmen! Liebe Kollegin Moser, Sie haben zwar
die Ministerin Bures angesprochen, aber da ich das Wohnpaket verhandelt habe, weise ich darauf hin, dass Ihrer
Aufmerksamkeit entgangen sein dürfte, dass wir für die thermische Sanierung im Wohnbau sehr viel Geld in die Hand
nehmen (Abg. Dr. Moser: Leider nur 100! Wir brauchen 300!) und dass die Infrastrukturprojekte ja dazu gedacht sind,
Arbeitsplätze zu schaffen, damit es nicht zu Arbeitslosigkeit kommt. Und das nützt den Menschen, Frau Kollegin Moser!
(Beifall bei der ÖVP.) '''
df.loc[mask, 'rede'] = rede_fehlend + rede_temp
Sonderfall, bei dem die Rede zu früh beginnt und das Ende fehlt.
mask = df.rede.str.startswith('Abgeordneter Dr. Michael Spindelegger: Ich bedanke mich für das Vertrauen und nehme die Wahl sehr gerne an. (Allgemeiner Beifall.)')
rede_temp = df[mask].iloc[0].rede
rede_fehlend = '''umzugehen. Wir sind dazu bereit und laden Sie alle hier noch einmal ein, bei dieser Aufklärungsarbeit mitzuwirken.
(Beifall bei der SPÖ und bei Abgeordneten der Grünen. – Abg. Grillitsch: Sie haben keine Verantwortung!)'''
start_pos = rede_temp.find('Abgeordneter Dr. Josef Cap (SPÖ)')
df.loc[mask, 'rede'] = rede_temp[start_pos:] + rede_fehlend
Bei Rednern aus der Regierung, wird deren Titel mitangeführt. Dieser muss gesondert behandelt werden. Übrigens beeindruckend, wie viele unterschiedliche Minister/Ministerinnen es gab - es sind 62. Zusätzlich gibt es noch andere "Titel", die nicht zur Regierung gehören, z.B. Volksanwalt, Schriftführerin. Diese werden auch gesondert erfasst.
TITEL_REGIERUNG = (
'Bundeskanzler',
'Bundesminister für Arbeit, Soziales und Konsumentenschutz',
'Bundesminister für Europa, Integration und Äußeres',
'Bundesminister für Finanzen',
'Bundesminister für Finanzen Vizekanzler',
'Bundesminister für Gesundheit',
'Bundesminister für Gesundheit, Familie und Jugend',
'Bundesminister für Inneres',
'Bundesminister für Justiz',
'Bundesminister für Kunst und Kultur, Verfassung und Medien',
'Bundesminister für Kunst und Kultur, Verfassung und öffentlichen Dienst',
'Bundesminister für Land- und Forstwirtschaft, Umwelt und Wasserwirtschaft',
'Bundesminister für Landesverteidigung',
'Bundesminister für Landesverteidigung und Sport',
'Bundesminister für Soziales und Konsumentenschutz',
'Bundesminister für Verkehr, Innovation und Technologie',
'Bundesminister für Wirtschaft und Arbeit',
'Bundesminister für Wirtschaft, Familie und Jugend',
'Bundesminister für Wissenschaft und Forschung',
'Bundesminister für Wissenschaft, Forschung und Wirtschaft',
'Bundesminister für Wissenschaft, Forschung und Wirtschaft Vizekanzler',
'Bundesminister für europäische und internationale Angelegenheiten',
'Bundesminister für europäische und internationale Angelegenheiten Vizekanzler',
'Bundesminister für soziale Sicherheit, Generationen und Konsumentenschutz',
'Bundesminister für soziale Sicherheit, Generationen und Konsumentenschutz Vizekanzler',
'Bundesminister im Bundeskanzleramt',
'Bundesminister ohne Portefeuille',
'Bundesministerin für Unterricht, Kunst und Kultur',
'Bundesministerin für Bildung und Frauen',
'Bundesministerin für Bildung, Wissenschaft und Kultur',
'Bundesministerin für Familien und Jugend',
'Bundesministerin für Finanzen',
'Bundesministerin für Frauen und öffentlichen Dienst',
'Bundesministerin für Frauen, Medien und Regionalpolitik',
'Bundesministerin für Frauen, Medien und öffentlichen Dienst',
'Bundesministerin für Gesundheit',
'Bundesministerin für Gesundheit und Frauen',
'Bundesministerin für Gesundheit, Familie und Jugend',
'Bundesministerin für Inneres',
'Bundesministerin für Justiz',
'Bundesministerin für Unterricht, Kunst und Kultur',
'Bundesministerin für Verkehr, Innovation und Technologie',
'Bundesministerin für Wissenschaft und Forschung',
'Bundesministerin für auswärtige Angelegenheiten',
'Bundesministerin für europäische und internationale Angelegenheiten',
'Bundesministerin für soziale Sicherheit, Generationen und Konsumentenschutz',
'Bundesministerin ohne Portefeuille',
'Staatssekretär im Bundesministerium für Finanzen',
'Staatssekretär im Bundesministerium für Verkehr, Innovation und Technologie',
'Staatssekretärin im Bundesministerium für soziale Sicherheit, Generationen und Konsumentenschutz',
'Staatssekretär im Bundeskanzleramt',
'Staatssekretärin im Bundesministerium für Wirtschaft, Familie und Jugend',
'Staatssekretär im Bundesministerium für europäische und internationale Angelegenheiten',
'Staatssekretärin im Bundesministerium für Verkehr, Innovation und Technologie',
'Staatssekretärin im Bundesministerium für Wirtschaft und Arbeit',
'Staatssekretär im Bundesministerium für Gesundheit und Frauen',
'Staatssekretär im Bundesministerium für soziale Sicherheit, Generationen und Konsumentenschutz',
'Staatssekretär im Bundesministerium für auswärtige Angelegenheiten',
'Staatssekretär im Bundesministerium für Inneres',
'Staatssekretärin im Bundeskanzleram',
'Staatssekretär im Bundesministerium für Wissenschaft, Forschung und Wirtschaft',
'Staatssekretärin im Bundesministerium für Finanzen'
)
TITEL_ANDERE = (
'Präsident des Rechnungshofes',
'Volksanwältin',
'Volksanwalt',
'Schriftführerin',
'Schriftführer',
'Präsident',
'Präsidentin',
'Berichterstatter',
'Berichterstatterin',
'Mitglied des Europäischen Parlaments'
)
# Stellt sicher, dass z.B. 'Bundesminister für europäische und internationale Angelegenheiten Vizekanzler' vor
# 'Bundesminister für europäische und internationale Angelegenheiten Vizekanzler'
TITEL_REGIERUNG = sorted(TITEL_REGIERUNG, reverse=True, key=len)
TITEL_ANDERE = sorted(TITEL_ANDERE, reverse=True, key=len)
len(TITEL_REGIERUNG)
62
# Funktion um aus der Rede den Redner (Anrede, Name, Partei) auszulesen
def formatieren(rede):
redner, rede_txt = rede.split(':', maxsplit=1)
redner = redner.replace('\n',' ').strip()
rede_txt = rede_txt.replace('\n',' ').strip()
for titel in TITEL_REGIERUNG:
if redner.startswith(titel):
redner_anrede = titel
redner_name = redner.replace(titel,'').strip()
# In Ausnahmefall noch Anmerkung bei Namen , z.B. (mit Beifall von ... begrüßt)
redner_name = re.sub(r'\([^)]*\)', '', redner_name)
redner_partei = 'Regierung'
rede_txt = re.sub(r'\([^)]*\)', '', rede_txt)
return pd.Series({'redner_anrede': redner_anrede, 'redner_name': redner_name,
'redner_partei': redner_partei, 'rede_txt': rede_txt})
for titel in TITEL_ANDERE:
if redner.startswith(titel):
redner_anrede = titel
redner_name = redner.replace(titel,'').strip()
# In Ausnahmefall noch Anmerkung bei Namen , z.B. (mit Beifall von ... begrüßt)
redner_name = re.sub(r'\([^)]*\)', '', redner_name)
redner_partei = 'Andere'
rede_txt = re.sub(r'\([^)]*\)', '', rede_txt)
return pd.Series({'redner_anrede': redner_anrede, 'redner_name': redner_name,
'redner_partei': redner_partei, 'rede_txt': rede_txt})
redner_anrede, redner_name = redner.split(' ', maxsplit=1)
redner_partei = redner_name[redner_name.rfind('(')+1:redner_name.rfind(')')].strip()
if redner_partei in ('zur Geschäftsbehandlung',
'in Übersetzung durch eine Gebärdensprachdolmetscherin',
'in Übersetzung durch einen Gebärdensprachdolmetscher',
'in Übersetzung durch die Gebärdensprachdolmetscherin',
'in Richtung SPÖ, die noch immer Beifall spendet',
'sich zunächst an Dr. Jarolim wendend',
'mit Beifall begrüßt',
'die Höhe des Rednerpultes einstellend',
'fortsetzend'):
redner_name = redner_name[:redner_name.rfind('(')]
if redner_name.count('(') > 0:
redner_partei = redner_name[redner_name.rfind('(')+1:redner_name.rfind(')')].strip()
else:
redner_partei = ''
redner_name = redner_name[:redner_name.rfind('(')].strip()
# Enfernen von Zwischenrufen, die sind immer in Klammern
rede_txt = re.sub(r'\([^)]*\)', '', rede_txt)
return pd.Series({'redner_anrede': redner_anrede, 'redner_name': redner_name,
'redner_partei': redner_partei, 'rede_txt': rede_txt})
%%time
df = pd.concat([df, df.rede.apply(formatieren)], axis=1)
Wall time: 8.38 s
df[:3]
datum | key | periode | rede | sitzung | rede_txt | redner_anrede | redner_name | redner_partei | |
---|---|---|---|---|---|---|---|---|---|
0 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Peter Pilz (Grüne): Frau Präs... | 28. Sitzung des\r\nNationalrates der Republik ... | Frau Präsidentin! Meine sehr verehrten Damen u... | Abgeordneter | Dr. Peter Pilz | Grüne |
1 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Günther Kräuter (SPÖ): Sehr g... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Herr Bundesmini... | Abgeordneter | Dr. Günther Kräuter | SPÖ |
2 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Heinz-Christian Strache (FPÖ): Se... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Sehr geehrter H... | Abgeordneter | Heinz-Christian Strache | FPÖ |
Abgeordnete (männlich und weiblich) haben am meisten Reden gehalten. Verhältnis weiblich zu männlich ist 1 zu 2,6. Der Bundesminister für Arbeit, Soziales und Konsumentenschutz war dann der fleißigste mit 161 Reden.
df.redner_anrede.value_counts()
Abgeordneter 20803 Abgeordnete 7968 Bundesminister für Arbeit, Soziales und Konsumentenschutz 161 Bundesminister für Land- und Forstwirtschaft, Umwelt und Wasserwirtschaft 154 Bundeskanzler 125 Bundesministerin für Justiz 104 Staatssekretär im Bundesministerium für Finanzen 104 Bundesministerin für Inneres 92 Bundesminister für Wirtschaft, Familie und Jugend 90 Bundesministerin für Unterricht, Kunst und Kultur 88 Bundesministerin für Verkehr, Innovation und Technologie 78 Bundesminister für Finanzen Vizekanzler 74 Bundesminister für Gesundheit 70 Präsident des Rechnungshofes 66 Bundesministerin für Finanzen 63 Staatssekretär im Bundeskanzleramt 49 Bundesminister für Wissenschaft und Forschung 47 Bundesminister für Landesverteidigung und Sport 42 Bundesminister für Wirtschaft und Arbeit 38 Bundesminister für Soziales und Konsumentenschutz 34 Bundesminister für Justiz 33 Bundesminister für Verkehr, Innovation und Technologie 29 Bundesminister für Finanzen 29 Staatssekretär im Bundesministerium für europäische und internationale Angelegenheiten 29 Bundesministerin für Gesundheit, Familie und Jugend 27 Bundesministerin für Frauen und öffentlichen Dienst 26 Staatssekretärin im Bundesministerium für Wirtschaft, Familie und Jugend 25 Bundesminister für Wissenschaft, Forschung und Wirtschaft Vizekanzler 24 Bundesminister für europäische und internationale Angelegenheiten Vizekanzler 22 Bundesministerin für Bildung und Frauen 22 ... Bundesministerin für Gesundheit 14 Bundesminister für Landesverteidigung 13 Bundesminister für Europa, Integration und Äußeres 12 Bundesministerin für Frauen, Medien und öffentlichen Dienst 12 Volksanwalt 12 Staatssekretärin im Bundesministerium für Verkehr, Innovation und Technologie 12 Staatssekretärin im Bundesministerium für Wirtschaft und Arbeit 11 Staatssekretär im Bundesministerium für Wissenschaft, Forschung und Wirtschaft 9 Bundesministerin für Familien und Jugend 8 Bundesministerin für europäische und internationale Angelegenheiten 8 Bundesminister für Wissenschaft, Forschung und Wirtschaft 8 Präsident 8 Berichterstatterin 7 Bundesministerin für soziale Sicherheit, Generationen und Konsumentenschutz 6 Staatssekretär im Bundesministerium für Inneres 6 Bundesministerin ohne Portefeuille 4 Bundesminister im Bundeskanzleramt 4 Bundesministerin für Wissenschaft und Forschung 4 Bundesminister für Kunst und Kultur, Verfassung und öffentlichen Dienst 3 Staatssekretärin im Bundesministerium für Finanzen 3 Bundesminister für soziale Sicherheit, Generationen und Konsumentenschutz 3 Bundesministerin für Frauen, Medien und Regionalpolitik 2 Staatssekretär im Bundesministerium für soziale Sicherheit, Generationen und Konsumentenschutz 2 Bundesministerin für Bildung, Wissenschaft und Kultur 1 Bundesministerin für Unterricht, Kunst und Kultur 1 Bundesministerin für Gesundheit und Frauen 1 Staatssekretär im Bundesministerium für Verkehr, Innovation und Technologie 1 Bundesminister für Gesundheit, Familie und Jugend 1 Bundesministerin für auswärtige Angelegenheiten 1 Bundesminister ohne Portefeuille 1 Name: redner_anrede, dtype: int64
len(df[df.redner_anrede == 'Abgeordneter']) / len(df[df.redner_anrede == 'Abgeordnete'])
2.6108182730923697
len(df[df.redner_anrede == 'Abgeordnete']) / len(df[df.redner_anrede == 'Abgeordneter'])
0.3830216795654473
Insgesamt gibt es 68 "Berufsbezeichnungen".
len(df.redner_anrede.unique())
68
Das Thema 'Kultur' wurde in den unterschiedlichsten Ministerien behandelt.
df.loc[df.redner_anrede.str.contains('Kultur'), 'redner_anrede'].value_counts()
Bundesministerin für Unterricht, Kunst und Kultur 88 Bundesminister für Kunst und Kultur, Verfassung und Medien 16 Bundesminister für Kunst und Kultur, Verfassung und öffentlichen Dienst 3 Bundesministerin für Unterricht, Kunst und Kultur 1 Bundesministerin für Bildung, Wissenschaft und Kultur 1 Name: redner_anrede, dtype: int64
df_temp = df.loc[df.redner_anrede.str.contains('Kultur'), ['redner_anrede', 'datum']]
df_temp.groupby([df.datum.dt.year, df.redner_anrede])['redner_anrede'].count()
datum redner_anrede 2007 Bundesministerin für Bildung, Wissenschaft und Kultur 1 Bundesministerin für Unterricht, Kunst und Kultur 8 2008 Bundesministerin für Unterricht, Kunst und Kultur 7 2009 Bundesministerin für Unterricht, Kunst und Kultur 15 2010 Bundesministerin für Unterricht, Kunst und Kultur 7 2011 Bundesministerin für Unterricht, Kunst und Kultur 12 2012 Bundesministerin für Unterricht, Kunst und Kultur 20 2013 Bundesministerin für Unterricht, Kunst und Kultur 1 Bundesministerin für Unterricht, Kunst und Kultur 18 2014 Bundesminister für Kunst und Kultur, Verfassung und Medien 7 Bundesminister für Kunst und Kultur, Verfassung und öffentlichen Dienst 3 Bundesministerin für Unterricht, Kunst und Kultur 1 2015 Bundesminister für Kunst und Kultur, Verfassung und Medien 9 Name: redner_anrede, dtype: int64
Wie hat sich das Verhätnis von Reden weiblicher Abgeordneter zu denen von männlichen über die Zeit entwickelt?
df_ratio = df.groupby(df.datum.dt.year)[['redner_anrede']].agg(lambda x:
sum(x == 'Abgeordnete') / sum(x == 'Abgeordneter') * 100)
df_ratio.columns = ['Frau pro Mann']
df_ratio[:3]
Frau pro Mann | |
---|---|
datum | |
2006 | 41.525424 |
2007 | 43.976494 |
2008 | 40.273224 |
sns.set(context='talk', style='whitegrid')
sns.barplot(x='datum', y='Frau pro Mann', data=df_ratio.reset_index())
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Reden von weiblichen Abgeordneten pro 100 Reden von männlichen')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Anzahl')
sns.plt.savefig('geschlecht.svg')
Nun schauen wir uns die Parteien an. Hier sieht man 2 Einträge, ohne Partei. Das wird manuell korregiert.
Im Folgenden behandle ich Reden von Regierungsmitgliedern unter der virtuellen Partei 'Regierung'.
df.redner_partei.value_counts()
SPÖ 7288 ÖVP 6670 FPÖ 5145 Grüne 4398 BZÖ 3301 Regierung 1894 STRONACH 1003 NEOS 687 ohne Klubzugehörigkeit 227 Andere 155 NEOS-LIF 50 2 Name: redner_partei, dtype: int64
Manuelle Korrektur für 2 Fälle, in denen die Partei fehlt.
df.loc[df.redner_partei == '', ['redner_name', 'redner_partei']]
redner_name | redner_partei | |
---|---|---|
2249 | Wolfgang Zanger | |
20333 | Peter Wurm |
df.loc[(df.redner_partei == '') & (df.redner_name == 'Peter Wurm'), 'redner_partei'] = 'FPÖ'
df.loc[(df.redner_partei == '') & (df.redner_name == 'Wolfgang Zanger'), 'redner_partei'] = 'FPÖ'
df.loc[df.redner_partei == 'Andere', 'redner_anrede'].value_counts()
Präsident des Rechnungshofes 66 Volksanwältin 19 Mitglied des Europäischen Parlaments 15 Berichterstatter 14 Präsidentin 14 Volksanwalt 12 Präsident 8 Berichterstatterin 7 Name: redner_anrede, dtype: int64
# NEOS und NEOS-LIF im folgenden als eine Partei betrachtet
df.loc[df.redner_partei == 'NEOS-LIF', 'redner_partei'] = 'NEOS'
# Behandle 'ohne Klubzugehörigkeit' und 'Andere' gemeinsam als 'Andere'.
# Das ist eine Vereinfachung, da Fokus auf den Parteien und Regierung liegt.
df.loc[df.redner_partei == 'ohne Klubzugehörigkeit', 'redner_partei'] = 'Andere'
df.redner_partei.value_counts()
SPÖ 7288 ÖVP 6670 FPÖ 5147 Grüne 4398 BZÖ 3301 Regierung 1894 STRONACH 1003 NEOS 737 Andere 382 Name: redner_partei, dtype: int64
Definieren Reihenfolge der Parteien und zugehörige Farben.
parteien_ordnung = ['Regierung',
'SPÖ',
'ÖVP',
'FPÖ',
'Grüne',
'BZÖ',
'STRONACH',
'NEOS',
'Andere']
# Farbennamen von http://www.luminoso.com/colors/
parteien_farben = ['grey', #Regierung
'red',
'black',
'blue',
'green',
'orange',
'yellow',
'pink',
'light grey'] #Andere
sns.palplot(sns.xkcd_palette(parteien_farben))
df.groupby(['redner_partei', 'periode'])[['key']].count().unstack()
key | |||
---|---|---|---|
periode | XXIII | XXIV | XXV |
redner_partei | |||
Andere | 30.0 | 215.0 | 137.0 |
BZÖ | 653.0 | 2648.0 | NaN |
FPÖ | 890.0 | 3071.0 | 1186.0 |
Grüne | 880.0 | 2517.0 | 1001.0 |
NEOS | NaN | NaN | 737.0 |
Regierung | 390.0 | 1076.0 | 428.0 |
SPÖ | 1546.0 | 4130.0 | 1612.0 |
STRONACH | NaN | 287.0 | 716.0 |
ÖVP | 1568.0 | 3623.0 | 1479.0 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.countplot(y='redner_partei', data=df, order=parteien_ordnung)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Reden pro Partei')
sns.set(font_scale=1)
sns.axlabel('Reden', '')
sns.plt.savefig('reden_pro_partei.svg')
Wie hat sich die relative Anzahl an Reden pro Partei über die Zeit verändert?
df_temp = df.groupby([df.datum.dt.year, 'redner_partei'])[['key']].count().unstack()
df_temp[:3]
key | |||||||||
---|---|---|---|---|---|---|---|---|---|
redner_partei | Andere | BZÖ | FPÖ | Grüne | NEOS | Regierung | SPÖ | STRONACH | ÖVP |
datum | |||||||||
2006 | 3.0 | 45.0 | 65.0 | 61.0 | NaN | 20.0 | 84.0 | NaN | 79.0 |
2007 | 13.0 | 337.0 | 447.0 | 466.0 | NaN | 205.0 | 856.0 | NaN | 834.0 |
2008 | 14.0 | 328.0 | 446.0 | 407.0 | NaN | 188.0 | 666.0 | NaN | 714.0 |
df_temp = df_temp.apply(lambda x: x / np.sum(x), axis=1) * 100
df_temp[:3]
key | |||||||||
---|---|---|---|---|---|---|---|---|---|
redner_partei | Andere | BZÖ | FPÖ | Grüne | NEOS | Regierung | SPÖ | STRONACH | ÖVP |
datum | |||||||||
2006 | 0.840336 | 12.605042 | 18.207283 | 17.086835 | NaN | 5.602241 | 23.529412 | NaN | 22.128852 |
2007 | 0.411653 | 10.671311 | 14.154528 | 14.756175 | NaN | 6.491450 | 27.105763 | NaN | 26.409120 |
2008 | 0.506696 | 11.871155 | 16.141875 | 14.730366 | NaN | 6.804198 | 24.104235 | NaN | 25.841477 |
df_temp = df_temp.stack().reset_index()
df_temp = df_temp.rename(columns={'redner_partei': 'Partei'})
df_temp[:3]
datum | Partei | key | |
---|---|---|---|
0 | 2006 | Andere | 0.840336 |
1 | 2006 | BZÖ | 12.605042 |
2 | 2006 | FPÖ | 18.207283 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.factorplot(x = 'datum', y = 'key', hue = 'Partei' , data = df_temp, size=8, hue_order=parteien_ordnung)
ax.set(ylim=(0, 30))
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('% Reden pro Partei')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Prozent')
sns.plt.savefig('reden_pro_partei_pro_jahr.svg')
Eine andere Darstellung der Verteilung der Reden pro Partei.
df_temp = (df.groupby([df.datum.dt.year, df.redner_partei])['key'].count()).unstack()
df_temp = df_temp[parteien_ordnung]
df_temp = df_temp.transpose()
mask = df_temp.isnull()
df_temp = df_temp.fillna(value=0)
df_temp = df_temp.astype('int')
df_temp[:13]
datum | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|---|---|---|---|---|---|---|
redner_partei | |||||||||||
Regierung | 20 | 205 | 188 | 237 | 181 | 255 | 208 | 190 | 203 | 185 | 22 |
SPÖ | 84 | 856 | 666 | 1062 | 811 | 848 | 777 | 622 | 786 | 699 | 77 |
ÖVP | 79 | 834 | 714 | 891 | 717 | 757 | 679 | 568 | 716 | 639 | 76 |
FPÖ | 65 | 447 | 446 | 769 | 619 | 653 | 564 | 447 | 592 | 494 | 51 |
Grüne | 61 | 466 | 407 | 632 | 496 | 517 | 460 | 403 | 489 | 418 | 49 |
BZÖ | 45 | 337 | 328 | 699 | 511 | 558 | 466 | 357 | 0 | 0 | 0 |
STRONACH | 0 | 0 | 0 | 0 | 0 | 0 | 68 | 256 | 349 | 295 | 35 |
NEOS | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 31 | 349 | 322 | 35 |
Andere | 3 | 13 | 14 | 29 | 82 | 41 | 51 | 14 | 22 | 87 | 26 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.heatmap(df_temp, annot=True, linewidths=.5, fmt='d', mask=mask)
#sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Reden (in 100 Reden)')
sns.set(font_scale=1)
sns.axlabel('Partei', 'Jahr')
#sns.plt.savefig('geschlecht.svg')
Wie hat sich das Verhältnis der Reden von weiblichen Abgeordneten zu denen von männlichen pro Partei (exkl. Regierung) über die Zeit entwickelt?
df_ratio = df.groupby([df.datum.dt.year, 'redner_partei'])[['redner_anrede']].agg(lambda x:
sum(x == 'Abgeordnete') / sum(x == 'Abgeordneter')*100)
df_ratio = df_ratio.reset_index()
df_ratio = df_ratio.rename(columns={'redner_partei': 'Partei', 'redner_anrede': 'Rednerin pro Redner'})
df_ratio = df_ratio.loc[df_ratio.Partei != 'Regierung']
df_ratio[:3]
datum | Partei | Rednerin pro Redner | |
---|---|---|---|
0 | 2006 | Andere | NaN |
1 | 2006 | BZÖ | 15.384615 |
2 | 2006 | FPÖ | 12.068966 |
parteien_ordnung_ohne_regierung = parteien_ordnung.copy()
parteien_ordnung_ohne_regierung.remove('Regierung')
parteien_farben_ohne_regierung = parteien_farben.copy()
parteien_farben_ohne_regierung.remove('grey')
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben_ohne_regierung))
ax = sns.factorplot(x = 'datum', y = 'Rednerin pro Redner', hue = 'Partei' , data = df_ratio, size=8,
hue_order=parteien_ordnung_ohne_regierung)
ax.set(ylim=(0, 110))
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Reden weiblicher Abgeordneter je 100 Reden von männlichen Abgeordneten')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Reden')
sns.plt.savefig('geschlecht_je_partei.svg')
Wie ist z.B. der Rückgang bei den NEOS zu erklären?
df[df.redner_partei == 'NEOS'].groupby([df.datum.dt.year, 'redner_anrede', 'redner_name'])[['key']].count().unstack('datum')
key | |||||
---|---|---|---|---|---|
datum | 2013 | 2014 | 2015 | 2016 | |
redner_anrede | redner_name | ||||
Abgeordnete | Claudia Angela Gamon, MSc (WU) | NaN | NaN | 6.0 | 3.0 |
Mag. Beate Meinl-Reisinger, MES | 4.0 | 50.0 | 33.0 | NaN | |
Mag. Dr. Angelika Rosa Mlinar | 3.0 | 13.0 | NaN | NaN | |
Abgeordneter | Dr. Nikolaus Scherak | 1.0 | 32.0 | 57.0 | 6.0 |
Dr. Rainer Hable | 8.0 | 55.0 | 19.0 | 1.0 | |
Josef Schellhorn | NaN | 21.0 | 34.0 | 4.0 | |
Mag. Christoph Vavrik | 1.0 | 13.0 | 15.0 | NaN | |
Mag. Dr. Matthias Strolz | 6.0 | 53.0 | 41.0 | 6.0 | |
Mag. Gerald Loacker | 4.0 | 55.0 | 54.0 | 9.0 | |
Mag. Nikolaus Alm | 1.0 | 24.0 | 26.0 | 4.0 | |
Mag. Nikolaus Scherak | 2.0 | NaN | NaN | NaN | |
Michael Pock | 1.0 | 33.0 | 37.0 | 2.0 |
df[df.redner_partei == 'STRONACH'].groupby([df.datum.dt.year, 'redner_anrede', 'redner_name'])[['key']].count().unstack('datum')
key | ||||||
---|---|---|---|---|---|---|
datum | 2012 | 2013 | 2014 | 2015 | 2016 | |
redner_anrede | redner_name | |||||
Abgeordnete | Dr. Jessi Lintl | NaN | NaN | 13.0 | 11.0 | NaN |
Dr. Kathrin Nachbaur | NaN | 7.0 | 51.0 | 18.0 | NaN | |
Elisabeth Kaufmann-Bruckberger | 16.0 | 16.0 | NaN | NaN | NaN | |
Ing. Waltraud Dietrich | NaN | 5.0 | 36.0 | 41.0 | 4.0 | |
Martina Schenk | NaN | 37.0 | 22.0 | 29.0 | 6.0 | |
Ulrike Weigerstorfer | NaN | NaN | 14.0 | 16.0 | 3.0 | |
Abgeordneter | Christoph Hagen | 21.0 | 65.0 | 35.0 | 47.0 | 7.0 |
Dr. Georg Vetter | NaN | 9.0 | 42.0 | 12.0 | NaN | |
Dr. Marcus Franz | NaN | 3.0 | 34.0 | 10.0 | NaN | |
Erich Tadler | 3.0 | 18.0 | NaN | NaN | NaN | |
Frank Stronach | NaN | 2.0 | 1.0 | NaN | NaN | |
Ing. Robert Lugar | 17.0 | 51.0 | 38.0 | 48.0 | 9.0 | |
Leopold Steinbichler | NaN | 5.0 | 41.0 | 46.0 | 6.0 | |
Rouven Ertlschweiger, MSc | NaN | NaN | 22.0 | 17.0 | NaN | |
Stefan Markowitz | 11.0 | 38.0 | NaN | NaN | NaN |
# from http://stackoverflow.com/questions/17507876/trying-to-count-words-in-a-string
def anzahl_woerter(txt):
return len(re.findall(r'\b\w+\b', txt))
anzahl_woerter('Johnny.Appleseed!is:a*good&farmer')
6
%%time
df['rede_anzahl_woerter'] = df.rede_txt.apply(anzahl_woerter)
Wall time: 8.65 s
df[:3]
datum | key | periode | rede | sitzung | rede_txt | redner_anrede | redner_name | redner_partei | rede_anzahl_woerter | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Peter Pilz (Grüne): Frau Präs... | 28. Sitzung des\r\nNationalrates der Republik ... | Frau Präsidentin! Meine sehr verehrten Damen u... | Abgeordneter | Dr. Peter Pilz | Grüne | 1743 |
1 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Günther Kräuter (SPÖ): Sehr g... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Herr Bundesmini... | Abgeordneter | Dr. Günther Kräuter | SPÖ | 1051 |
2 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Heinz-Christian Strache (FPÖ): Se... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Sehr geehrter H... | Abgeordneter | Heinz-Christian Strache | FPÖ | 2044 |
df_temp = (df.groupby(df.datum.dt.year)
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp[:3]
woerter | reden | woerter_pro_rede | |
---|---|---|---|
datum | |||
2006 | 228325 | 357 | 639.565826 |
2007 | 1914967 | 3158 | 606.386004 |
2008 | 1531344 | 2763 | 554.232356 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.barplot(x='datum', y='woerter_pro_rede', data=df_temp.reset_index())
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Anzahl an Worten pro Rede je Jahr')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Wörter pro Rede')
sns.plt.savefig('woerter_pro_rede_je_jahr.svg')
df_temp = (df.groupby('redner_partei')
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp[:3]
woerter | reden | woerter_pro_rede | |
---|---|---|---|
redner_partei | |||
Andere | 264319 | 382 | 691.934555 |
BZÖ | 2214068 | 3301 | 670.726447 |
FPÖ | 3264382 | 5147 | 634.230037 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.barplot(x='redner_partei', y='woerter_pro_rede', data=df_temp.reset_index(), order=parteien_ordnung)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Anzahl an Worten pro Rede je Partei')
sns.set(font_scale=1)
sns.axlabel('Partei', 'Wörter pro Rede')
sns.plt.savefig('woerter_pro_rede_je_partei.svg')
df_temp = (df.groupby([df.datum.dt.year, 'redner_partei'])
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp = df_temp.woerter_pro_rede
df_temp = df_temp.unstack()
df_temp = df_temp / 100
df_temp = df_temp[parteien_ordnung]
df_temp = df_temp.transpose()
df_temp[:3]
datum | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|---|---|---|---|---|---|---|
redner_partei | |||||||||||
Regierung | 9.391000 | 11.010146 | 8.871117 | 9.293797 | 9.777956 | 8.756353 | 9.385240 | 8.544526 | 10.221330 | 9.871946 | 7.312727 |
SPÖ | 5.639405 | 4.340479 | 4.421877 | 4.239689 | 4.433662 | 4.677441 | 4.614363 | 4.818955 | 4.607774 | 4.690973 | 4.569870 |
ÖVP | 5.384051 | 4.149580 | 4.015714 | 4.644961 | 4.617238 | 4.767503 | 5.004050 | 4.872518 | 4.784330 | 4.864679 | 4.488947 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.heatmap(df_temp, annot=True, linewidths=.5)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Wörter pro Rede (in 100 Wörtern)')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Partei')
#sns.plt.savefig('geschlecht.svg')
df.sort_values(by='rede_anzahl_woerter', ascending=False)[:10]
datum | key | periode | rede | sitzung | rede_txt | redner_anrede | redner_name | redner_partei | rede_anzahl_woerter | |
---|---|---|---|---|---|---|---|---|---|---|
9704 | 2009-07-10 | XXIV_NRSITZ_00032 | XXIV | Berichterstatter Jakob Auer: Herr Präsident! M... | 32. Sitzung des\r\nNationalrates der Republik ... | Herr Präsident! Meine sehr verehrten Damen und... | Berichterstatter | Jakob Auer | Andere | 9546 |
7980 | 2011-10-20 | XXIV_NRSITZ_00124 | XXIV | Bundesministerin für Finanzen Mag. Dr. Maria T... | 124. Sitzung des\r\nNationalrates der Republik... | Sehr geehrter Herr Bundespräsident! Sehr geehr... | Bundesministerin für Finanzen | Mag. Dr. Maria Theresia Fekter | Regierung | 8508 |
5041 | 2010-11-30 | XXIV_NRSITZ_00086 | XXIV | Bundesminister für Finanzen Vizekanzler Dipl.-... | 86. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrter Herr Bundespräsident! Frau Präsi... | Bundesminister für Finanzen Vizekanzler | Dipl.-Ing. Josef Pröll | Regierung | 8201 |
9488 | 2009-04-21 | XXIV_NRSITZ_00019 | XXIV | Bundesminister für Finanzen Vizekanzler Dipl.-... | 19. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrter Herr Bundespräsident! Frau Präsi... | Bundesminister für Finanzen Vizekanzler | Dipl.-Ing. Josef Pröll | Regierung | 7760 |
10382 | 2014-04-29 | XXV_NRSITZ_00021 | XXV | Bundesminister für Finanzen Vizekanzler Dr. Mi... | 21. Sitzung des\r\nNationalrates der Republik ... | Sehr geschätzter Herr Bundespräsident! Frau Pr... | Bundesminister für Finanzen Vizekanzler | Dr. Michael Spindelegger | Regierung | 7580 |
15139 | 2007-03-29 | XXIII_NRSITZ_00017 | XXIII | Bundesminister für Finanzen Vizekanzler Mag. W... | 17. Sitzung des Nationalrates der Republik Öst... | Grüß Gott, meine Damen und Herren! Sehr geehrt... | Bundesminister für Finanzen Vizekanzler | Mag. Wilhelm Molterer | Regierung | 7154 |
5222 | 2012-10-16 | XXIV_NRSITZ_00173 | XXIV | Bundesministerin für Finanzen Mag. Dr. Maria T... | 173. Sitzung des\r\nNationalrates der Republik... | Stabile Finanzen durch Reformen, Wachstum durc... | Bundesministerin für Finanzen | Mag. Dr. Maria Theresia Fekter | Regierung | 7058 |
26027 | 2015-10-14 | XXV_NRSITZ_00096 | XXV | Bundesminister für Finanzen Dr. Johann Georg S... | 96. Sitzung des\r\nNationalrates der Republik ... | Liebe Österreicherinnen und Österreicher! Gesc... | Bundesminister für Finanzen | Dr. Johann Georg Schelling | Regierung | 7013 |
3022 | 2007-01-17 | XXIII_NRSITZ_00009 | XXIII | Bundeskanzler Dr. Alfred Gusenbauer: Sehr vere... | 9. Sitzung des Nationalrates der Republik Öste... | Sehr verehrter Herr Bundespräsident! Frau Präs... | Bundeskanzler | Dr. Alfred Gusenbauer | Regierung | 6669 |
925 | 2008-12-03 | XXIV_NRSITZ_00006 | XXIV | Abgeordneter Fritz Neugebauer (ÖVP): Ich danke... | 6. Sitzung des Nationalrates\r\nder Republik Ö... | Ich danke für die Zustimmung und nehme die Wah... | Abgeordneter | Fritz Neugebauer | ÖVP | 5958 |
df_temp = df.groupby([df.datum.dt.year, 'redner_partei'])[['rede_anzahl_woerter']].sum().unstack()
df_temp = df_temp.apply(lambda x: x / np.sum(x), axis=1) * 100
df_temp = df_temp.stack().reset_index()
df_temp = df_temp.rename(columns={'redner_partei': 'Partei', '0': 'rede_anzahl_woerter'})
df_temp[:3]
datum | Partei | rede_anzahl_woerter | |
---|---|---|---|
0 | 2006 | Andere | 1.263112 |
1 | 2006 | BZÖ | 14.180664 |
2 | 2006 | FPÖ | 18.936166 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.factorplot(x = 'datum', y = 'rede_anzahl_woerter', hue = 'Partei' , data = df_temp, size=8,
hue_order=parteien_ordnung)
ax.set(ylim=(0, 25))
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('% Wörter pro Partei')
sns.set(font_scale=1)
sns.axlabel('Jahr', 'Prozent')
sns.plt.savefig('woerter_pro_partei_je_jahr.svg')
df_temp = (df.groupby([df.datum.dt.year, df.redner_partei])['rede_anzahl_woerter'].sum()).unstack()
df_temp = df_temp[parteien_ordnung]
df_temp = df_temp.transpose()
mask = df_temp.isnull()
df_temp = df_temp.fillna(value=0)
df_temp = round(df_temp / 10000)
df_temp = df_temp.astype('int')
df_temp[:13]
datum | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|---|---|---|---|---|---|---|
redner_partei | |||||||||||
Regierung | 2 | 23 | 17 | 22 | 18 | 22 | 20 | 16 | 21 | 18 | 2 |
SPÖ | 5 | 37 | 29 | 45 | 36 | 40 | 36 | 30 | 36 | 33 | 4 |
ÖVP | 4 | 35 | 29 | 41 | 33 | 36 | 34 | 28 | 34 | 31 | 3 |
FPÖ | 4 | 35 | 29 | 44 | 36 | 39 | 35 | 30 | 38 | 34 | 4 |
Grüne | 4 | 35 | 28 | 45 | 35 | 37 | 34 | 29 | 35 | 30 | 3 |
BZÖ | 3 | 25 | 20 | 43 | 36 | 37 | 33 | 24 | 0 | 0 | 0 |
STRONACH | 0 | 0 | 0 | 0 | 0 | 0 | 4 | 16 | 22 | 19 | 2 |
NEOS | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 2 | 24 | 22 | 2 |
Andere | 0 | 2 | 2 | 3 | 5 | 3 | 4 | 1 | 2 | 3 | 1 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.heatmap(df_temp, annot=True, linewidths=.5, fmt='d', mask=mask)
#sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Anzahl Wörter (in 10 000)')
sns.set(font_scale=1)
sns.axlabel('Partei', 'Jahr')
#sns.plt.savefig('geschlecht.svg')
df_temp = (df.groupby(df.datum.dt.month)
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp[:3]
woerter | reden | woerter_pro_rede | |
---|---|---|---|
datum | |||
1 | 1451522 | 2399 | 605.052939 |
2 | 948267 | 1569 | 604.376673 |
3 | 1844419 | 3118 | 591.539128 |
sns.set(context='talk', style='whitegrid')
sns.barplot(x='datum', y='woerter_pro_rede', data=df_temp.reset_index())
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Wörter pro Rede je Monat')
sns.set(font_scale=1)
sns.axlabel('Monat', 'Wörter je Rede')
#sns.plt.savefig('geschlecht.svg')
df_temp = (df.groupby([df.datum.dt.month, df.datum.dt.year])
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp = df_temp.woerter_pro_rede
df_temp = df_temp.unstack()
df_temp = df_temp / 100
df_temp[:3]
datum | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 |
---|---|---|---|---|---|---|---|---|---|---|---|
datum | |||||||||||
1 | NaN | 7.631205 | 5.632826 | 6.441859 | 5.539053 | 5.275805 | 6.136543 | 5.756801 | 5.433277 | 6.967581 | 5.909652 |
2 | NaN | NaN | NaN | 4.769273 | 6.194412 | 9.291200 | 6.283447 | 6.452460 | 7.005679 | 5.728421 | 5.209588 |
3 | NaN | 6.475766 | 5.470185 | 4.990970 | 5.759085 | 6.186834 | 5.779534 | 5.672059 | 6.402978 | 6.566250 | NaN |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.heatmap(df_temp, annot=True, linewidths=.5)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Wörter pro Rede (in 100 Wörtern)')
sns.set(font_scale=1)
sns.axlabel('Monat', 'Jahr')
#sns.plt.savefig('geschlecht.svg')
df_temp = (df.groupby(df.datum.dt.dayofweek)
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp[:3]
woerter | reden | woerter_pro_rede | |
---|---|---|---|
datum | |||
0 | 359142 | 408 | 880.250000 |
1 | 2583637 | 4030 | 641.100993 |
2 | 6304870 | 10512 | 599.778349 |
sns.set(context='talk', style='whitegrid')
ax = sns.barplot(y='datum', x='woerter_pro_rede', data=df_temp.reset_index(), orient='h')
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Wörter pro Rede je Wochentag')
sns.set(font_scale=1)
sns.axlabel('Wörter je Rede', 'Wochentag')
labels = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
ax.set_yticklabels(labels)
sns.plt.savefig('woerter_pro_wochentag.svg')
df_temp = (df.groupby([df.datum.dt.dayofweek, df.datum.dt.month])
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp = df_temp.woerter_pro_rede
df_temp = df_temp.unstack()
df_temp = df_temp / 100
df_temp.index = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa']
df_temp[:3]
datum | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Mo | NaN | 7.500510 | 8.205641 | 11.145172 | 10.253333 | 9.475714 | NaN | NaN | NaN | 10.499474 | NaN | NaN |
Di | 6.258969 | 6.939865 | 6.970000 | 6.220626 | 6.744286 | 5.200458 | 5.587575 | NaN | 8.563448 | 7.280685 | 5.812907 | 5.925711 |
Mi | 6.879826 | 5.657642 | 6.314768 | 6.034325 | 6.004242 | 6.200072 | 5.150375 | 9.020833 | 6.674188 | 6.255066 | 5.834187 | 5.507077 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
sns.heatmap(df_temp, annot=True, linewidths=.5)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Durchschnittliche Wörter pro Rede (in 100 Wörtern)')
sns.set(font_scale=1)
sns.axlabel('Monat', 'Wochentag')
#sns.plt.savefig('geschlecht.svg')
df_temp = (df[df.redner_anrede.isin(['Abgeordnete', 'Abgeordneter'])].groupby(['redner_anrede'])
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp = df_temp.reset_index().rename(columns={'redner_anrede': 'Redner'})
df_temp[:13]
Redner | woerter | reden | woerter_pro_rede | |
---|---|---|---|---|
0 | Abgeordnete | 4118454 | 7968 | 516.874247 |
1 | Abgeordneter | 12151490 | 20803 | 584.122002 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(['pink', 'light blue']))
ax = sns.barplot(x='woerter_pro_rede', y = 'Redner' , data = df_temp)
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Wörte pro Rede für weibliche und männliche Abgeordnete')
sns.set(font_scale=1)
sns.axlabel('Wörter', 'Redner')
#sns.plt.savefig('geschlecht.svg')
df_temp = (df[df.redner_anrede.isin(['Abgeordnete', 'Abgeordneter'])].groupby(['redner_partei', 'redner_anrede'])
.agg({'rede_anzahl_woerter': 'sum', 'key': 'count'})
.rename(columns={'rede_anzahl_woerter': 'woerter', 'key': 'reden'}))
df_temp['woerter_pro_rede'] = df_temp['woerter'] / df_temp['reden']
df_temp = df_temp.reset_index().rename(columns={'redner_anrede': 'Redner'})
df_temp[:13]
redner_partei | Redner | woerter | reden | woerter_pro_rede | |
---|---|---|---|---|---|
0 | Andere | Abgeordnete | 8076 | 16 | 504.750000 |
1 | Andere | Abgeordneter | 104681 | 211 | 496.118483 |
2 | BZÖ | Abgeordnete | 235753 | 399 | 590.859649 |
3 | BZÖ | Abgeordneter | 1978315 | 2902 | 681.707443 |
4 | FPÖ | Abgeordnete | 367174 | 647 | 567.502318 |
5 | FPÖ | Abgeordneter | 2897208 | 4500 | 643.824000 |
6 | Grüne | Abgeordnete | 1337864 | 1980 | 675.688889 |
7 | Grüne | Abgeordneter | 1812393 | 2418 | 749.542184 |
8 | NEOS | Abgeordnete | 77864 | 112 | 695.214286 |
9 | NEOS | Abgeordneter | 425448 | 625 | 680.716800 |
10 | SPÖ | Abgeordnete | 1084493 | 2599 | 417.273182 |
11 | SPÖ | Abgeordneter | 2218925 | 4689 | 473.219237 |
12 | STRONACH | Abgeordnete | 207047 | 345 | 600.136232 |
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(['pink', 'light blue']))
ax = sns.factorplot(x = 'redner_partei', y = 'woerter_pro_rede', hue = 'Redner' , data = df_temp, size=8,
kind='bar', order=parteien_ordnung_ohne_regierung)
#ax.set(ylim=(0, 1.2))
sns.despine()
sns.set(font_scale=1.5)
sns.plt.title('Wörte pro Rede für weibliche und männliche Abgeordnete')
sns.set(font_scale=1)
sns.axlabel('Partei', 'Wörter')
sns.plt.savefig('woerter_pro_geschlecht_je_partei.svg')
df.redner_name.value_counts()
Mag. Werner Kogler 394 Herbert Scheibner 354 Heinz-Christian Strache 317 Dr. Josef Cap 314 Ing. Robert Lugar 297 Ursula Haubner 285 Ing. Peter Westenthaler 284 Karl Öllinger 279 Christoph Hagen 277 Josef Bucher 267 Dr. Walter Rosenkranz 259 Sigisbert Dolinschek 259 Dipl.-Ing. Dr. Wolfgang Pirklhuber 257 Dr. Gabriela Moser 256 Mag. Albert Steinhauser 247 Dr. Dagmar Belakowitsch-Jenewein 240 Gerald Grosz 233 Mag. Ewald Stadler 228 Otto Pendl 228 Kai Jan Krainer 228 Dr. Peter Fichtenbauer 204 Martina Schenk 204 Dr. Christoph Matznetter 202 Ing. Norbert Hofer 198 Dr. Eva Glawischnig-Piesczek 194 Mag. Rainer Widmann 191 Dr. Ruperta Lichtenecker 187 Dr. Peter Pilz 183 Bernhard Themessl 180 Karlheinz Kopf 178 ... Mag. Nikolaus Scherak 2 Dipl.-Ing. Uwe Scheuch 2 , betraut mit der Leitung des Bundesministeriums für Wissenschaft und Forschung, Dr. Reinhold Mitterlehner 2 Dr. Johannes Hahn, betraut mit der Leitung des Bundesministeriums für Justiz 2 Dr. Alfred Finz 2 Mag. Evelyn Regner 2 Michel Reimon, MBA 2 Mag. Hilmar Kabas 1 Julian Schmid 1 Werner Faymann 1 Mag. Ulrike Lunacek 1 Sylvia Prettenthaler 1 Mag. Karl Schweitzer 1 Dr. Ulrike Baumgartner-Gabitzer 1 Hermann Brückl 1 Eugen Freund 1 Hedwig Wechner 1 Mag. Hans Peter Doskozil 1 Heinz Kurt Becker 1 Mag. Sonja Steßl-Mühlbacher 1 Hartmann Lautenschlager 1 Mag. Eduard Mainoni 1 Dipl.- Ing. Andrä Rupprechter 1 Dr. Reinhold Mitterlehner, betraut mit der Leitung des Bundesministeriums für Wissenschaft und Forschung 1 Dr. Andreas Khol 1 Rosemarie Bauer 1 Alois Stöger 1 Irene Szep 1 Alois Stöger, dipl. 1 Erika Scharer 1 Name: redner_name, dtype: int64
df.loc[df.redner_name.str.contains('Alois Stöger'), 'redner_name'].value_counts()
Alois Stöger, diplômé 87 Alois Stöger, dipl. 1 Alois Stöger 1 Name: redner_name, dtype: int64
df.loc[df.redner_name.str.contains('Alois Stöger'), 'redner_name'] = 'Alois Stöger, diplômé'
df.loc[df.redner_name.str.contains('Andrä Rupprechter'), 'redner_name'].value_counts()
Dipl.-Ing. Andrä Rupprechter 41 Dipl.- Ing. Andrä Rupprechter 1 Name: redner_name, dtype: int64
df.loc[df.redner_name.str.contains('Andrä Rupprechter'), 'redner_name'] = 'Dipl.-Ing. Andrä Rupprechter'
df.loc[df.redner_name.str.contains('Reinhold Mitterlehner'), 'redner_name'].value_counts()
Dr. Reinhold Mitterlehner 150 , betraut mit der Leitung des Bundesministeriums für Wissenschaft und Forschung, Dr. Reinhold Mitterlehner 2 Dr. Reinhold Mitterlehner, betraut mit der Leitung des Bundesministeriums für Wissenschaft und Forschung 1 Name: redner_name, dtype: int64
df.loc[df.redner_name.str.contains('Reinhold Mitterlehner'), 'redner_name'] = 'Dr. Reinhold Mitterlehner'
df.loc[df.redner_name.str.contains('Johannes Hahn'), 'redner_name'].value_counts()
Dr. Johannes Hahn 25 Dr. Johannes Hahn, betraut mit der Leitung des Bundesministeriums für Justiz 2 Name: redner_name, dtype: int64
df.loc[df.redner_name.str.contains('Johannes Hahn'), 'redner_name'] = 'Dr. Johannes Hahn'
df.redner_name.value_counts()
Mag. Werner Kogler 394 Herbert Scheibner 354 Heinz-Christian Strache 317 Dr. Josef Cap 314 Ing. Robert Lugar 297 Ursula Haubner 285 Ing. Peter Westenthaler 284 Karl Öllinger 279 Christoph Hagen 277 Josef Bucher 267 Sigisbert Dolinschek 259 Dr. Walter Rosenkranz 259 Dipl.-Ing. Dr. Wolfgang Pirklhuber 257 Dr. Gabriela Moser 256 Mag. Albert Steinhauser 247 Dr. Dagmar Belakowitsch-Jenewein 240 Gerald Grosz 233 Mag. Ewald Stadler 228 Kai Jan Krainer 228 Otto Pendl 228 Dr. Peter Fichtenbauer 204 Martina Schenk 204 Dr. Christoph Matznetter 202 Ing. Norbert Hofer 198 Dr. Eva Glawischnig-Piesczek 194 Mag. Rainer Widmann 191 Dr. Ruperta Lichtenecker 187 Dr. Peter Pilz 183 Bernhard Themessl 180 Karlheinz Kopf 178 ... Frank Stronach 3 Daniela Holzinger-Vogtenhuber, BA 3 Dr. Werner Fasslabend 3 Dr. Alfred Finz 2 Mag. Nikolaus Scherak 2 Dipl.-Ing. Uwe Scheuch 2 Michel Reimon, MBA 2 Dipl.-Ing. Karlheinz Klement 2 Hans-Jörg Jenewein 2 Mag. Evelyn Regner 2 Mag. Othmar Karas, MBL-HSG 2 Irene Szep 1 Hermann Brückl 1 Hartmann Lautenschlager 1 Sylvia Prettenthaler 1 Mag. Sonja Steßl-Mühlbacher 1 Mag. Ulrike Lunacek 1 Mag. Hans Peter Doskozil 1 Mag. Eduard Mainoni 1 Rosemarie Bauer 1 Mag. Hilmar Kabas 1 Werner Faymann 1 Eugen Freund 1 Dr. Ulrike Baumgartner-Gabitzer 1 Mag. Karl Schweitzer 1 Hedwig Wechner 1 Erika Scharer 1 Heinz Kurt Becker 1 Dr. Andreas Khol 1 Julian Schmid 1 Name: redner_name, dtype: int64
df[:3]
datum | key | periode | rede | sitzung | rede_txt | redner_anrede | redner_name | redner_partei | rede_anzahl_woerter | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Peter Pilz (Grüne): Frau Präs... | 28. Sitzung des\r\nNationalrates der Republik ... | Frau Präsidentin! Meine sehr verehrten Damen u... | Abgeordneter | Dr. Peter Pilz | Grüne | 1743 |
1 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Dr. Günther Kräuter (SPÖ): Sehr g... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Herr Bundesmini... | Abgeordneter | Dr. Günther Kräuter | SPÖ | 1051 |
2 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | Abgeordneter Heinz-Christian Strache (FPÖ): Se... | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Sehr geehrter H... | Abgeordneter | Heinz-Christian Strache | FPÖ | 2044 |
df = df.drop('rede', axis=1)
import string
string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
translator = str.maketrans({key: None for key in string.punctuation})
df['rede_clean'] = df.rede_txt.str.translate(translator)
#df.to_pickle('df_03.pkl')
from wordcloud import WordCloud
# https://github.com/amueller/word_cloud
# Achtung, ich habe an der Erweiterung wordcloud - die für englische Sprache entwickelt wurde - etwas
# herumgebastelt, um zu verhindern, dass ein 's' am Ende eines Worts als Pluar interpretiert wird.
# Ansonst würden zum Beispiel die Wörter hau und Haus zusammen erfasst.
import matplotlib.pyplot as plt
%matplotlib inline
#df = pd.read_pickle('df_03.pkl')
df[:3]
datum | key | periode | sitzung | rede_txt | redner_anrede | redner_name | redner_partei | rede_anzahl_woerter | rede_clean | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | 28. Sitzung des\r\nNationalrates der Republik ... | Frau Präsidentin! Meine sehr verehrten Damen u... | Abgeordneter | Dr. Peter Pilz | Grüne | 1743 | Frau Präsidentin Meine sehr verehrten Damen un... |
1 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Herr Bundesmini... | Abgeordneter | Dr. Günther Kräuter | SPÖ | 1051 | Sehr geehrte Frau Präsidentin Herr Bundesminis... |
2 | 2007-07-05 | XXIII_NRSITZ_00028 | XXIII | 28. Sitzung des\r\nNationalrates der Republik ... | Sehr geehrte Frau Präsidentin! Sehr geehrter H... | Abgeordneter | Heinz-Christian Strache | FPÖ | 2044 | Sehr geehrte Frau Präsidentin Sehr geehrter He... |
#stopword Liste 1 von http://members.unine.ch/jacques.savoy/clef/index.html
STOPWORDS_GENERAL = set([x.strip() for x in open('germanST.txt').read().split('\n')])
STOPWORDS_GENERAL = STOPWORDS_GENERAL.union(set(('nämlich',)))
#stopword Liste 2 von https://solariz.de/de/downloads/6/german-enhanced-stopwords.htm
#STOPWORDS_GENERAL = set([x.strip() for x in open('stopwords_2.txt').read().split('\n')])
len(STOPWORDS_GENERAL)
580
def wc(df_temp, titel=None, dateiname=False):
text = ' '.join(df_temp)
# take relative word frequencies into account, lower max_font_size
# wordcloud = WordCloud().generate(text)
wordcloud = WordCloud(max_font_size=40, relative_scaling=.5, background_color='white',
scale=3, random_state=42,
stopwords = STOPWORDS_GENERAL).generate(text)
plt.figure(figsize=(16,8))
plt.imshow(wordcloud)
plt.axis("off")
if titel:
plt.title(titel)
plt.show()
if dateiname:
wordcloud.to_file(dateiname)
wc(df.rede_clean, titel='Gesamt', dateiname='wc_gesamt.png')
#for periode in df.periode.unique():
# wc(df.loc[df.periode == periode, 'rede_clean'], titel=periode)
df.redner_partei.value_counts()
SPÖ 7288 ÖVP 6670 FPÖ 5147 Grüne 4398 BZÖ 3301 Regierung 1894 STRONACH 1003 NEOS 737 Andere 382 Name: redner_partei, dtype: int64
for partei in ('SPÖ', 'ÖVP', 'Grüne', 'FPÖ', 'BZÖ', 'Regierung', 'STRONACH', 'NEOS'):
wc(df.loc[df.redner_partei == partei, 'rede_clean'], titel=partei)
def wc_woerter(df_temp, titel=None, max_words=1000):
text = ' '.join(df_temp)
# take relative word frequencies into account, lower max_font_size
# wordcloud = WordCloud().generate(text)
wordcloud = WordCloud(max_words = max_words, stopwords = STOPWORDS_GENERAL).generate(text)
df_out = pd.DataFrame(wordcloud.words_, columns=['wort', titel])
df_out.index = df_out.wort
df_out = df_out.drop('wort', axis=1)
return df_out
%%time
#parteien = ('SPÖ', 'ÖVP', 'Grüne', 'FPÖ', 'BZÖ', 'Regierung', 'STRONACH', 'NEOS')
#parteien = ('SPÖ', 'ÖVP', 'Grüne', 'FPÖ', 'BZÖ', 'STRONACH', 'NEOS')
#parteien = ('SPÖ', 'ÖVP', 'Grüne', 'FPÖ')
parteien = ('Regierung', 'SPÖ', 'ÖVP', 'FPÖ', 'Grüne')
df_woerter = pd.DataFrame()
for partei in parteien:
df_temp = wc_woerter(df.loc[df.redner_partei == partei, 'rede_clean'], titel=partei)
if df_woerter.empty:
df_woerter = df_temp
else:
df_woerter = df_woerter.merge(df_temp, how='outer', left_index=True, right_index=True)
df_woerter_durchschnitt = wc_woerter(df.loc[df.redner_partei.isin(parteien),'rede_clean'],
titel='durchschnitt')
df_woerter = df_woerter.merge(df_woerter_durchschnitt, how='outer', left_index=True, right_index=True)
df_woerter = df_woerter / df_woerter.sum()
df_woerter = df_woerter.fillna(value=0)
df_woerter_delta = df_woerter.apply(lambda x: x - x['durchschnitt'], axis=1)
Wall time: 44.2 s
df_woerter_min = df_woerter.drop('durchschnitt', axis=1)
df_woerter_min = df_woerter_min.apply(lambda x: x - min(x), axis=1)
df_woerter_min[:10]
Regierung | SPÖ | ÖVP | FPÖ | Grüne | |
---|---|---|---|---|---|
wort | |||||
AMS | 0.000392 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
Abgeordnete | 0.002270 | 0.000000 | 0.000129 | 0.000119 | 0.000643 |
Abgeordneten | 0.000461 | 0.000124 | 0.000000 | 0.001217 | 0.001495 |
Abgeordneter | 0.002591 | 0.000037 | 0.000000 | 0.000565 | 0.000366 |
Abkommen | 0.000087 | 0.000202 | 0.000246 | 0.000137 | 0.000000 |
Abs | 0.000000 | 0.000610 | 0.000887 | 0.000478 | 0.000541 |
Abschaffung | 0.000000 | 0.000000 | 0.000000 | 0.000454 | 0.000000 |
Abschluss | 0.000481 | 0.000334 | 0.000331 | 0.000000 | 0.000000 |
Absicherung | 0.000000 | 0.000331 | 0.000000 | 0.000000 | 0.000000 |
Abstimmung | 0.000000 | 0.000000 | 0.000000 | 0.000400 | 0.000367 |
parteien_mapping = {'Regierung': 'Partei D',
'SPÖ' : 'Partei A',
'ÖVP' : 'Partei E',
'FPÖ' : 'Partei C',
'Grüne' : 'Partei B'}
for titel in df_woerter.columns.drop('durchschnitt'):
woerter_plus = df_woerter_delta.loc[df_woerter_delta[titel] > 0, titel]
woerter_minus = df_woerter_delta.loc[df_woerter_delta[titel] < 0, titel] * (-1)
wordcloud_plus = WordCloud(max_font_size=40, relative_scaling=.5, background_color='white',
scale=3, random_state=42, max_words=30)
wordcloud_minus = WordCloud(max_font_size=40, relative_scaling=.5, background_color='black',
scale=3, random_state=42, max_words=30)
wordcloud_plus = WordCloud.generate_from_frequencies(wordcloud_plus,woerter_plus.to_dict().items())
wordcloud_minus = WordCloud.generate_from_frequencies(wordcloud_minus,woerter_minus.to_dict().items())
plt.figure(figsize=(16,8))
plt.subplot(1, 2, 1)
plt.imshow(wordcloud_plus)
plt.axis("off")
plt.title(parteien_mapping[titel] + ' - überdurchschnittlich' )
plt.subplot(1, 2, 2)
plt.imshow(wordcloud_minus)
plt.axis("off")
plt.title(parteien_mapping[titel] + ' - unterdurchschnittlich' )
plt.savefig('wc_raetsel_' + parteien_mapping[titel].replace(' ','_') + '.png',
transparent=True, bbox_inches='tight', pad_inches=0)
plt.show()
df_woerter.loc[df_woerter.index.str.contains('grüne', flags=re.IGNORECASE)]
Regierung | SPÖ | ÖVP | FPÖ | Grüne | durchschnitt | |
---|---|---|---|---|---|---|
wort | ||||||
Grüne | 0.000000 | 0.000000 | 0.000327 | 0.000000 | 0.001366 | 0.000508 |
Grünen | 0.000781 | 0.001331 | 0.002206 | 0.002772 | 0.002957 | 0.002140 |
grüne | 0.000000 | 0.000000 | 0.000000 | 0.000412 | 0.000000 | 0.000000 |
df_woerter.loc[df_woerter.index.str.contains('freiheit', flags=re.IGNORECASE)]
Regierung | SPÖ | ÖVP | FPÖ | Grüne | durchschnitt | |
---|---|---|---|---|---|---|
wort | ||||||
Freiheit | 0.0 | 0.000000 | 0.000000 | 0.000391 | 0.000000 | 0.000000 |
Freiheitliche | 0.0 | 0.000000 | 0.000000 | 0.001745 | 0.000406 | 0.000551 |
Freiheitlichen | 0.0 | 0.000769 | 0.000675 | 0.002813 | 0.000985 | 0.001199 |
df_woerter.loc[df_woerter.index.str.contains('volksp', flags=re.IGNORECASE)]
Regierung | SPÖ | ÖVP | FPÖ | Grüne | durchschnitt | |
---|---|---|---|---|---|---|
wort | ||||||
Volkspartei | 0.0 | 0.0 | 0.000611 | 0.0 | 0.000428 | 0.0 |
df_woerter.loc[df_woerter.index.str.contains('sozial', flags=re.IGNORECASE)]
Regierung | SPÖ | ÖVP | FPÖ | Grüne | durchschnitt | |
---|---|---|---|---|---|---|
wort | ||||||
Sozialdemokraten | 0.000000 | 0.000542 | 0.000000 | 0.000333 | 0.000000 | 0.000000 |
Sozialdemokratie | 0.000000 | 0.000526 | 0.000000 | 0.000502 | 0.000000 | 0.000000 |
Sozialminister | 0.000000 | 0.000331 | 0.000000 | 0.000374 | 0.000000 | 0.000000 |
Sozialpartner | 0.000356 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
sozial | 0.000451 | 0.000625 | 0.000419 | 0.000381 | 0.000462 | 0.000480 |
soziale | 0.000825 | 0.001002 | 0.000745 | 0.000751 | 0.000782 | 0.000838 |
sozialen | 0.000795 | 0.000928 | 0.000583 | 0.000488 | 0.000494 | 0.000662 |
sample = {'Regierung': ('Regierung',),
'SPÖ': ('SPÖ', 'Sozialdemokraten'),
'ÖVP': ('ÖVP', 'Volkspartei'),
'Grüne': ('Grüne', 'Grünen'),
'FPÖ': ('FPÖ', 'Freiheitlichen', 'Freiheitliche')
}
woerter = [item for sublist in sample.values() for item in sublist]
df_temp = df_woerter[df_woerter.index.isin(woerter)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
for temp_partei in sample:
df_temp.loc[temp_partei] = sum([df_temp.loc[wort,:] for wort in sample[temp_partei]])
df_temp = df_temp.drop(labels=[wort for wort in sample[temp_partei] if wort != temp_partei], axis=0)
df_temp = df_temp.reindex(index=df_temp.columns)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit ausgewählter Wörter')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', '')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
sns.plt.savefig('wc_parteien.svg')
top_woerter = list()
for partei in parteien:
top_woerter.extend(list(df_woerter.sort_values(by=partei, ascending=False)[:15][partei].index))
top_woerter = set(top_woerter)
sample = top_woerter
df_temp = df_woerter[df_woerter.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
df_temp = df_temp.sort_values(by='Regierung', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit ausgewählter Wörter')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', '')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
#sns.plt.savefig('wc_partei_top_woerter.svg')
sample = ('Österreich', 'Europa', 'Frage', 'Millionen', 'Milliarden', 'Prozent',
'Kollegen', 'wichtig', 'glaube',
'Antrag', 'sagen', 'genau', 'wissen')
df_temp = df_woerter[df_woerter_delta.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
#df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
#df_temp = df_temp.sort_values(by='Regierung', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit pro Wort je Partei')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', 'Ausgewählte Wörter')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
sns.plt.savefig('wc_partei_woerter.svg')
sample = ('Österreich', 'Frage', 'Millionen', 'Prozent',
'Kollegen', 'wichtig', 'glaube',
'heißt', 'Antrag', 'sagen', 'genau', 'wissen')
df_temp = df_woerter[df_woerter_delta.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
#df_temp = df_temp.sort_values(by='Regierung', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit pro Wort je Partei')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', 'Ausgewählte Wörter')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
#sns.plt.savefig('wc_partei_woerter.svg')
sample = (#'Österreich', 'Europa',
'Griechenland', 'ESM',
'Hypo', 'Kärnten',
'Steuerzahler', 'Steuerreform',
'Flüchtlinge',
' ',
# 'Millionen', 'Milliarden',
'Finanzminister', 'Finanzministerin',
' ',
'Faymann',
' ',
'BZÖ', 'Stronach', 'NEOS',
# 'Molterer', 'Pröll', 'Spindelegger', 'Mitterlehner',
)
df_temp = df_woerter[df_woerter_delta.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
#df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
#df_temp = df_temp.sort_values(by='Regierung', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit pro Wort je Partei')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', 'Ausgewählte Wörter')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
#sns.plt.savefig('wc_partei_woerter.svg')
df.datum.dt.year.value_counts()
2009 4319 2011 3629 2014 3506 2010 3417 2012 3273 2007 3158 2015 3139 2013 2888 2008 2763 2016 371 2006 357 Name: datum, dtype: int64
%%time
jahre = range(2007,2016)
df_woerter = pd.DataFrame()
for jahr in jahre:
df_temp = wc_woerter(df.loc[df.datum.dt.year == jahr, 'rede_clean'], titel=str(jahr))
if df_woerter.empty:
df_woerter = df_temp
else:
df_woerter = df_woerter.merge(df_temp, how='outer', left_index=True, right_index=True)
df_woerter_durchschnitt = wc_woerter(df.loc[df.redner_partei.isin(parteien),'rede_clean'],
titel='durchschnitt')
df_woerter = df_woerter.merge(df_woerter_durchschnitt, how='outer', left_index=True, right_index=True)
df_woerter = df_woerter / df_woerter.sum()
df_woerter = df_woerter.fillna(value=0)
df_woerter_delta = df_woerter.apply(lambda x: x - x['durchschnitt'], axis=1)
Wall time: 47.2 s
df_woerter_min = df_woerter.drop('durchschnitt', axis=1)
df_woerter_min = df_woerter_min.apply(lambda x: x - min(x), axis=1)
df_woerter_min[:10]
2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | |
---|---|---|---|---|---|---|---|---|---|
wort | |||||||||
AMA | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000365 | 0.000000 | 0.000000 | 0.000000 |
AUA | 0.000000 | 0.000753 | 0.000725 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
Abgeordnete | 0.000247 | 0.000214 | 0.000395 | 0.000000 | 0.000218 | 0.000370 | 0.000271 | 0.000344 | 0.000205 |
Abgeordneten | 0.000407 | 0.000673 | 0.000660 | 0.000173 | 0.000000 | 0.000214 | 0.000297 | 0.000326 | 0.000093 |
Abgeordneter | 0.000364 | 0.000457 | 0.000530 | 0.000271 | 0.000048 | 0.000289 | 0.000135 | 0.000000 | 0.000137 |
Abkommen | 0.000391 | 0.000594 | 0.000000 | 0.000457 | 0.000433 | 0.000884 | 0.000565 | 0.000546 | 0.000511 |
Abs | 0.000289 | 0.000013 | 0.000265 | 0.000000 | 0.000016 | 0.000260 | 0.000353 | 0.000119 | 0.000018 |
Abschaffung | 0.000345 | 0.000403 | 0.000000 | 0.000000 | 0.000398 | 0.000392 | 0.000000 | 0.000000 | 0.000425 |
Abschluss | 0.000000 | 0.000336 | 0.000000 | 0.000000 | 0.000000 | 0.000345 | 0.000000 | 0.000000 | 0.000000 |
Abstimmung | 0.000000 | 0.000459 | 0.000346 | 0.000000 | 0.000000 | 0.000340 | 0.000357 | 0.000000 | 0.000000 |
for titel in df_woerter.columns.drop('durchschnitt'):
woerter_plus = df_woerter_delta.loc[df_woerter_delta[titel] > 0, titel]
woerter_minus = df_woerter_delta.loc[df_woerter_delta[titel] < 0, titel] * (-1)
wordcloud_plus = WordCloud(max_font_size=40, relative_scaling=.5, background_color='white',
scale=3, random_state=42, max_words=30)
wordcloud_minus = WordCloud(max_font_size=40, relative_scaling=.5, background_color='black',
scale=3, random_state=42, max_words=30)
wordcloud_plus = WordCloud.generate_from_frequencies(wordcloud_plus,woerter_plus.to_dict().items())
wordcloud_minus = WordCloud.generate_from_frequencies(wordcloud_minus,woerter_minus.to_dict().items())
plt.imshow(wordcloud_plus)
plt.axis("off")
plt.title(titel + ' - überdurchschnittlich' )
plt.savefig('wc_jahr_' + titel + '.png', transparent=True, bbox_inches='tight', pad_inches=0)
plt.show()
df_woerter[:3]
2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | durchschnitt | |
---|---|---|---|---|---|---|---|---|---|---|
wort | ||||||||||
AMA | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000365 | 0.000000 | 0.000000 | 0.00000 | 0.000000 |
AUA | 0.000000 | 0.000753 | 0.000725 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.00000 | 0.000000 |
Abgeordnete | 0.001302 | 0.001268 | 0.001449 | 0.001055 | 0.001273 | 0.001425 | 0.001325 | 0.001398 | 0.00126 | 0.001347 |
top_woerter = list()
for jahr in df_woerter.columns:
top_woerter.extend(list(df_woerter.sort_values(by=jahr, ascending=False)[:20][jahr].index))
top_woerter = set(top_woerter)
top_woerter = list()
for jahr in df_woerter.columns:
top_woerter.extend(list(df_woerter_delta.sort_values(by=jahr, ascending=False)[:5][jahr].index))
top_woerter = set(top_woerter)
sample = top_woerter
df_temp = df_woerter[df_woerter.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
#df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
df_temp = df_temp.sort_values(by='2015', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit ausgewählter Wörter')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', '')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
#sns.plt.savefig('wc_jahr_top_woerter.svg')
sample = (#'Österreich', 'Europa',
'Griechenland', 'Schuldenbremse', 'ESM', 'Zypern',
'Insolvenz', 'Hypo', 'Kärnten', 'Bank',
'Steuerzahler', 'Steuerreform',
'Flüchtlinge',
' ',
# 'Millionen', 'Milliarden',
'Finanzminister', 'Finanzministerin',
' ',
'Gusenbauer', 'Faymann',
' ',
'BZÖ', 'Stronach', 'NEOS',
# 'Molterer', 'Pröll', 'Spindelegger', 'Mitterlehner',
)
df_temp = df_woerter[df_woerter_delta.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
#df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
#df_temp = df_temp.sort_values(by='Regierung', ascending=False)
plt.figure(figsize=(16,10))
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit ausgewählter Wörter')
sns.set(font_scale=1)
sns.axlabel('Jahr', '')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
sns.plt.savefig('wc_jahr_woerter.svg')
sample = ('Österreich', 'Europa',
'Griechenland', 'Schuldenbremse', 'ESM', 'Zypern',
'Insolvenz', 'Hypo', 'Kärnten', 'Bank',
'Millionen', 'Milliarden',
'Gusenbauer', 'Faymann',
'Molterer', 'Pröll', 'Spindelegger', 'Mitterlehner',
'Finanzminister', 'Finanzministerin',
'Steuerzahler', 'Steuerreform')
df_temp = df_woerter[df_woerter_delta.index.isin(sample)]
df_temp = df_temp.drop('durchschnitt', axis=1)
df_temp = df_temp * 10000
df_temp = df_temp.reindex(index=sample)
df_temp = df_temp.apply(lambda x: (x - min(x))/max(x-min(x)), axis=1)
#df_temp = df_temp.sort_values(by='Regierung', ascending=False)
sns.set(context='talk', style='whitegrid', palette=sns.xkcd_palette(parteien_farben))
ax = sns.heatmap(df_temp, annot=False, linewidths=.5)
#sns.despine()
plt.yticks(rotation=0)
sns.set(font_scale=1.5)
sns.plt.title('Häufigkeit pro Wort je Partei')
sns.set(font_scale=1)
sns.axlabel('Partei der Redner', 'Ausgewählte Wörter')
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, df_temp.max().max()])
cbar.set_ticklabels(['selten', 'oft'])
#sns.plt.savefig('wc_jahr_woerter.svg')