Datenbearbeitung und Datenstandardisierung¶
Maja Lichman
In [3]:
import pandas as pd
from IPython.display import HTML
from IPython.core.display import HTML
from IPython.display import Image
import re
import gender_guesser.detector as gender
import matplotlib.pyplot as plt
import requests
import geonamescache
from geonamescache import GeonamesCache
import numpy as np
import plotly.express as px
from translate import Translator
from geopy.geocoders import Nominatim
1. Daten¶
In [5]:
display(Image(filename='Bild.jpg', width=600, height=500))
Bildquelle: Von Bundesarchiv, Bild 183-1987-0928-500 / CC-BY-SA 3.0, CC BY-SA 3.0 de, Link
Die Daten, die mir für dieses Projekt zur Verfügung standen, wurden von der ehemaligen Studentin der Universität Stuttgart Stephanie Bujak erstellt. Als Datengrundlage diente ihr das Biographisches Handbuch der deutschsprachigen Emigration nach 1933, herausgegeben 1980/83 von Werner Röder und Herbert Strauss. Die Studentin hat die Einträge des digitalen Handbuchs mithilfe der Python-Skripte in eine Excel-Tabelle extrahiert. Die Tabelle enthält damit personen- und ausreisebezogene Informationen zu 7.871 Personen, die nach der Machtergreifung der Nationalsozialisten aus Deutschland, Österreich und der deutschsprachigen Tschechoslowakei ausgewandert sind. Die Tabelle bildet momentan die Grundlage der digitalen Datenbank auf der Webseite Emigration und Exil von Wissenschaftlern und Ingenieuren 1930-1950. Die Daten in der Tabelle sind aber nicht standardisiert und aus diesem Grund für statistische Untersuchungen kaum geeignet. In diesem Projekt wird der Standardisierungsprozess dieser Daten gezeigt. Anschließend werden die standardisierten Daten mit bar_plot, bar_polar, heatmap und scatter_geo visualisiert.
Bild: Handbuchseite
In [10]:
df_alt = pd.read_excel("Tabelle.xlsx") # Tabelle in Python offnen
In [11]:
df_alt.shape # Anzahl Zeilen und Spalten
Out[11]:
(7871, 32)
In [12]:
colnames = df_alt.columns.tolist()
print(colnames) # Spaltennamen
['PersonID', 'Name', 'Geburtsdatum,-ort/ggf. Sterbedatum,-ort', 'Beruf', 'Zieljahr1', 'Zielort1', 'Zieljahr2', 'Zielort2', 'Zieljahr3', 'Zielort3', 'Zieljahr4', 'Zielort4', 'Zieljahr5', 'Zielort5', 'Zieljahr6', 'Zielort6', 'Zieljahr7', 'Zielort7', 'Zieljahr8', 'Zielort8', 'Zieljahr9', 'Zielort9', 'Zieljahr10', 'Zielort10', 'Zieljahr11', 'Zielort11', 'Zieljahr12', 'Zielort12', 'Zieljahr13', 'Zielort13', 'Zieljahr14', 'Zielort14']
In [13]:
HTML(df_alt.iloc[:10, :4].to_html(index=False))
Out[13]:
PersonID | Name | Geburtsdatum,-ort/ggf. Sterbedatum,-ort | Beruf |
---|---|---|---|
1 | Abel, August | geb. 19. Dez. 1887 Gelsenkirchen, gest. 18. Aug. 1962 Frankfurt/M.; | Journalist |
2 | Abel, Emil | b. Vienna 2 June 1875, d. London 3 Apr. 1958. | prof. of chemistry |
3 | Abel, Paul, Dr. jur. | geb. 21. März 1874 Wien, gest. 10. Mai 1971 London; | Rechtsanwalt |
4 | Abeles, Paul William | b. Mistelbach near Vienna 17 Jan. 1897. | civil engineer |
5 | Abeles, Robert Heinz | b. Vienna 14 Jan. 1926. | prof. of biochemistry |
6 | Abelmann, Walter H | b. Frankfurt/M 16 May 1921. | prof. of medicine |
7 | Aber, Adolf | b. Apolda, Thuringia, Ger. 28 Jan. 1893, d. London 21 May 1960. | musicologist |
8 | Aber, Felix, Dr. phil. | geb. 11. Apr. 1895 Breslau, gest. 14. Jan. 1964 New York; | Rabbiner |
9 | Abraham, Claude Kurt (fmly. Kurt Jakob Abraham) | b. Lorsch, Hessen, Ger. 13 Dec. 1931. | prof. of French |
10 | Abraham, Heinz, Dr. | geb. 30. Juni 1911 Allenstein/Ostpr.; | Diplomat, Historiker |
Die Spalten [1] bis [3] enthalten folgende Daten:
- Name: Nachnamen und Vornamen in einer Spalte, oft mit Zusatzinfo in Klammern oder nach Komma
- Geburtsdatum,-ort/ggf. Sterbedatum,-ort: Angaben zu Geburtsort und Geburtsdatum sowie ggf. zu Sterbeort und Sterbedatum in einer Spalte. Manche Eintrage auf Deutsch, manche auf Englisch
- Beruf: die Spalte ist ebenfalls zweisprachig, enthält Angaben zu Beruf der Personen, manchmal kommen Mehrfachnennungen vor
In [15]:
HTML(df_alt.iloc[:10, 4:19].to_html(index=False))
Out[15]:
Zieljahr1 | Zielort1 | Zieljahr2 | Zielort2 | Zieljahr3 | Zielort3 | Zieljahr4 | Zielort4 | Zieljahr5 | Zielort5 | Zieljahr6 | Zielort6 | Zieljahr7 | Zielort7 | Zieljahr8 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1934.0 | Afrika | 1948.0 | Deutschland | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1938.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1938.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1939.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1939.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | Switzerland | 1939.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1939.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1938.0 | France | 1946.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | Moskau | 1937.0 | Spain | 1939.0 | France | NaN | Moskau | NaN | Deutschland | NaN | NaN | NaN | NaN | NaN |
Die Spalten [4] bis [32] enthalten emigrationsbezogene Daten:
- Zieljahr1 bis Zieljahr14: Angaben zu Ausreisejahren, bereits standardisiert. Die Spalte Zieljahr1 gibt den Jahr der ersten Ausreise aus dem deutschsprachigen Land an. Die weiteren Spalten sind mit Werten besetzt, falls eine Person während der Emigrationsperiode mehrmals die Zielländer gewechselt hat
- Zielort1 bis Zielort14: Angabe zu einem oder mehreren Zielorten. Nicht standardisiert. Enthält Einträge aud Englisch und Deutsch, Abkürzungen der Ländernamen wie z. B. USA oder UK. Manchmal stehen in der Spalte auch nicht Länder sondern Städte
2. Ermittlung der Berufsgruppe Politik¶
In diesem Projekt wird für die Standardisierung, Bearbeitung und nachfolgende Visualisierung beispielhaft die Berufsgruppe Politik
gewählt.
Die Personen, die als Politiker tätig waren, wurden mit Buchstabenstrings gesucht.
In [19]:
Beruf = df_alt["Beruf"].tolist() # Spalte Beruf als Liste
In [20]:
df_alt['Beruf'].head(20).to_list()
Out[20]:
['Journalist', 'prof. of chemistry', 'Rechtsanwalt', 'civil engineer', 'prof. of biochemistry', 'prof. of medicine', 'musicologist', 'Rabbiner', 'prof. of French', 'Diplomat,\xa0Historiker', 'prof. of political science', 'composer of light opera,\xa0film scores', 'Gewerkschaftsfunktionär', 'dancer,\xa0choreographer,\xa0teacher', 'conductor,\xa0music director', 'Fürsorgerin,\xa0Museumsdirektorin', 'Prediger,\xa0Pädagoge', 'Politiker,\xa0Publizist', 'journalist', 'Hochschullehrer']
In [21]:
Beruf = list(map(str, Beruf)) #Liste Beruf als String-Liste
Beruf = [element.replace("\xa0 ", " ") for element in Beruf] #Entfernung der non-breaking space
Beruf = [wort.lower() for wort in Beruf] #Berufe kleinschreiben
Berufsgruppe = [] #neue Liste "Berufsgruppe" öffnen
In [22]:
for beruf in Beruf:
if "politik" in beruf or "funktionär" in beruf: # Suche mit den Strings
Berufsgruppe.append("Politik")
else:
Berufsgruppe.append("andere Berufsgruppen")
In [23]:
print(Berufsgruppe[:20])
['andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'Politik', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'andere Berufsgruppen', 'Politik', 'andere Berufsgruppen', 'andere Berufsgruppen']
In [24]:
df_alt.insert(4, 'Berufsgruppe', Berufsgruppe) # neue Liste mit Berufsgruppe als Spalte
In [25]:
HTML(df_alt.iloc[:10, :5].to_html(index=False))
Out[25]:
PersonID | Name | Geburtsdatum,-ort/ggf. Sterbedatum,-ort | Beruf | Berufsgruppe |
---|---|---|---|---|
1 | Abel, August | geb. 19. Dez. 1887 Gelsenkirchen, gest. 18. Aug. 1962 Frankfurt/M.; | Journalist | andere Berufsgruppen |
2 | Abel, Emil | b. Vienna 2 June 1875, d. London 3 Apr. 1958. | prof. of chemistry | andere Berufsgruppen |
3 | Abel, Paul, Dr. jur. | geb. 21. März 1874 Wien, gest. 10. Mai 1971 London; | Rechtsanwalt | andere Berufsgruppen |
4 | Abeles, Paul William | b. Mistelbach near Vienna 17 Jan. 1897. | civil engineer | andere Berufsgruppen |
5 | Abeles, Robert Heinz | b. Vienna 14 Jan. 1926. | prof. of biochemistry | andere Berufsgruppen |
6 | Abelmann, Walter H | b. Frankfurt/M 16 May 1921. | prof. of medicine | andere Berufsgruppen |
7 | Aber, Adolf | b. Apolda, Thuringia, Ger. 28 Jan. 1893, d. London 21 May 1960. | musicologist | andere Berufsgruppen |
8 | Aber, Felix, Dr. phil. | geb. 11. Apr. 1895 Breslau, gest. 14. Jan. 1964 New York; | Rabbiner | andere Berufsgruppen |
9 | Abraham, Claude Kurt (fmly. Kurt Jakob Abraham) | b. Lorsch, Hessen, Ger. 13 Dec. 1931. | prof. of French | andere Berufsgruppen |
10 | Abraham, Heinz, Dr. | geb. 30. Juni 1911 Allenstein/Ostpr.; | Diplomat, Historiker | andere Berufsgruppen |
In [26]:
df_alt['Berufsgruppe'].value_counts() # Anzahl der gefundenen Politiker
Out[26]:
Berufsgruppe andere Berufsgruppen 6437 Politik 1434 Name: count, dtype: int64
Es wurden insgesamt 1434 Vertreter der Berufsgruppe Poltik gefunden. Die Zeilen mit Information zu diesen Personen werden im neuen Data Frame df abgespeichert.
In [28]:
df = df_alt[df_alt['Berufsgruppe'].apply(lambda x: 'Politik' in str(x))] #Zeilen mit gefundenen Politiker herausfiltern
In [29]:
df.shape
Out[29]:
(1434, 33)
In [30]:
HTML(df.iloc[10:20, 1:5].to_html(index=False))
Out[30]:
Name | Geburtsdatum,-ort/ggf. Sterbedatum,-ort | Beruf | Berufsgruppe |
---|---|---|---|
Aenderl, Franz Xaver | geb. 25. Nov. 1883 Steinweg b. Regensburg, gest. 20. Okt. 1951 Kulmbach/Oberfr.; | Publizist, Politiker | Politik |
Albert, Peter Wenzel (von), Dr. | k.A. | Politiker | Politik |
Alexander, Henry Joachim, Dr. phil., Dr. jur. | geb. 4. Jan. 1897; | Rechtsanwalt, Verbandsfunktionär | Politik |
Alexander, Kurt, Dr. jur. | geb. 13. Aug. 1892 Krefeld, gest. 18. Febr. 1962 New York; | Rechtsanwalt, Verbandsfunktionär | Politik |
Alexander, Walter, Dr. jur. | geb. 20. März 1878 Berlin, gest. 20. Apr. 1949 New York; | Kommunalbeamter, Verbandsfunktionär | Politik |
Alfons, Anton | geb. 17. Jan. 1898 Wampersdorf b. Mödling/Niederösterr.; | Parteifunktionär | Politik |
Alliger, Ladislaus | geb. 1898 (?), gest. 1942 in GB; | Gewerkschaftsfunktionär | Politik |
Allina, Heinrich | geb. 24. Nov. 1878 Schaffa/Mähren, gest. 10. Dez. 1953 Wien; | Politiker, Gewerkschaftsfunktionär | Politik |
Alroy, Efraim (bis 1938 Spiegel, Hermann) | geb. 15. Aug. 1915 Hamburg; | Verbandsfunktionär | Politik |
Alterthum, Martin, Dr. jur. | geb. 31. Aug. 1887 Bernberg/Saale, gest. 12. Febr. 1976 Tel Aviv; | Richter, Verbandsfunktionär | Politik |
3. Standardisierung der Namen¶
Zuerst werden die Namen der Personen standardisiert. Die Vor- und Nachnamen sollen in separaten Spalten stehen, die Zusatzinformationen, welche nach Vor- und Nachnamen vorkommen, sollen entfernt werden. Hierfür wurden die Einträge der einzelnen Spalten nach den ersten Kommas getrennt. Danach wurde das erste Element herausgefiltert und in einer neuen Liste Nachname abgespeichert. Das zweite Element wurde entsprechend in einer neuen Liste Vorname gespeichert. Anschließend wurden aus der Liste Vorname mit regulären Ausdrücken alle Zusatzinformationen wie Titel (z. B. Adelstitel, akademischer Grad) sowie die ursprünglichen Namen oder Pseudonyme entfernt, die entweder in Klammern oder nach einem Komma standen. Bei der Entfernung der Zusatzinfos in Klammern wurde die Zusatzbedingung eingeführt, dass diese nur entfernt werden, wenn diese nach einem Leerzeichen folgen. Dies war notwendig, da viele Vornamen teilweise ebenfalls in Klammern standen, wie beispielsweise Arndt, H(einz) W(olfgang) und nicht entfernt werden sollten.
In [33]:
df['Name'].head(20).to_list() # noch nicht standardisierte Namen
Out[33]:
['Abrahamowicz, Uriel (urspr. Walter)', 'Abusch, Alexander', 'Ackermann, Manfred', 'Adam, Wilhelm (Willi)', 'Adams (bis 1962 Cammnitzer), Ellen C.', 'Adler, Friedrich Wolfgang (Fritz), Dr. rer. nat.', 'Adler, Gerson', 'Adler, Max Kurt, Dr. rer. pol.', 'Adler-Rudel, Salomon (Shalom)', 'Adolph (urspr. Adolf), Alfred', 'Aenderl, Franz Xaver', 'Albert, Peter Wenzel (von), Dr.', 'Alexander, Henry Joachim, Dr. phil., Dr. jur.', 'Alexander, Kurt, Dr. jur.', 'Alexander, Walter, Dr. jur.', 'Alfons, Anton', 'Alliger, Ladislaus', 'Allina, Heinrich', 'Alroy, Efraim (bis 1938 Spiegel, Hermann)', 'Alterthum, Martin, Dr. jur.']
In [34]:
Name = df["Name"].tolist() # Spalte "Namen" als Liste
string_Name = list(map(str, Name)) #Liste als String-Liste
Nachname = [element.split(',', 1)[0] for element in string_Name] #liste der Nachnamen (Elemente vor ersten Komma)
Vorname = [element.split(',', 1)[-1] for element in string_Name] #Liste der Vorname (Elemente nach ersten Komma)
In [35]:
print(Nachname[:100]) #noch nicht standardisierten Nachnamen
['Abrahamowicz', 'Abusch', 'Ackermann', 'Adam', 'Adams (bis 1962 Cammnitzer)', 'Adler', 'Adler', 'Adler', 'Adler-Rudel', 'Adolph (urspr. Adolf)', 'Aenderl', 'Albert', 'Alexander', 'Alexander', 'Alexander', 'Alfons', 'Alliger', 'Allina', 'Alroy', 'Alterthum', 'Altmaier', 'Altrichter', 'Amter', 'Anders-Naumann', 'Apfel', 'Appelt', 'Arnold', 'Arnsberg', 'Aron', 'Arp', 'Arzt', 'Atlasz', 'Auerbach', 'Auerbach', 'Aufhäuser', 'Ausch', 'Aviad', 'Avidan', 'Avidar (urspr. Wroclawski)', 'Avnery', 'Avriel (urspr. Uiberall)', 'Azania', 'Baade', 'Babel', 'Bach', 'Bachman', 'Bachmann', 'Badt', 'Baender', 'Bäsel', 'Bahnik', 'Ballin', 'Bandmann', 'Bar-Giora (urspr. Bamberger)', 'Bar-Menachem', 'Bartel', 'Barth', 'Bato (urspr. Berliner)', 'Bauer', 'Bauer', 'Bauer', 'Bauernfeind', 'Bayern', 'Becher', 'Beck', 'Beck', 'Becker', 'Becker', 'Becker', 'Becker', 'Becker', 'Beckmann', 'Beckmann', 'Behrisch', 'Bein', 'Beling', 'Benda', 'Benedikt', 'Benfey', 'Benjamin', 'Benkovics (Benkovic)', 'Berczeller', 'Berger', 'Berger', 'Berger', 'Bernhard', 'Bernstein', 'Bertz', 'Beuer', 'Beuttel', 'Beyer', 'Beyth', 'Bill', 'Bindel', 'Binder', 'Binner', 'Birnbaum', 'Bischoff', 'Bitan (urspr. Baumgarten)', 'Blanc']
In [36]:
Nachname = [re.sub(r'\s\([^)]*\)', '', wort) for wort in Nachname] # Entfernung der Strings, die in Klammern nach einem Leerzeichen stehen
In [37]:
print(Nachname[:100]) # standardisierte Nachnamen
['Abrahamowicz', 'Abusch', 'Ackermann', 'Adam', 'Adams', 'Adler', 'Adler', 'Adler', 'Adler-Rudel', 'Adolph', 'Aenderl', 'Albert', 'Alexander', 'Alexander', 'Alexander', 'Alfons', 'Alliger', 'Allina', 'Alroy', 'Alterthum', 'Altmaier', 'Altrichter', 'Amter', 'Anders-Naumann', 'Apfel', 'Appelt', 'Arnold', 'Arnsberg', 'Aron', 'Arp', 'Arzt', 'Atlasz', 'Auerbach', 'Auerbach', 'Aufhäuser', 'Ausch', 'Aviad', 'Avidan', 'Avidar', 'Avnery', 'Avriel', 'Azania', 'Baade', 'Babel', 'Bach', 'Bachman', 'Bachmann', 'Badt', 'Baender', 'Bäsel', 'Bahnik', 'Ballin', 'Bandmann', 'Bar-Giora', 'Bar-Menachem', 'Bartel', 'Barth', 'Bato', 'Bauer', 'Bauer', 'Bauer', 'Bauernfeind', 'Bayern', 'Becher', 'Beck', 'Beck', 'Becker', 'Becker', 'Becker', 'Becker', 'Becker', 'Beckmann', 'Beckmann', 'Behrisch', 'Bein', 'Beling', 'Benda', 'Benedikt', 'Benfey', 'Benjamin', 'Benkovics', 'Berczeller', 'Berger', 'Berger', 'Berger', 'Bernhard', 'Bernstein', 'Bertz', 'Beuer', 'Beuttel', 'Beyer', 'Beyth', 'Bill', 'Bindel', 'Binder', 'Binner', 'Birnbaum', 'Bischoff', 'Bitan', 'Blanc']
In [38]:
print(Vorname[:50]) # noch nicht standardisierten Vornamen
[' Uriel (urspr. Walter)', ' Alexander', ' Manfred', ' Wilhelm (Willi)', ' Ellen C.', ' Friedrich Wolfgang (Fritz), Dr. rer. nat.', ' Gerson', ' Max Kurt, Dr. rer. pol.', ' Salomon (Shalom)', ' Alfred', ' Franz Xaver', ' Peter Wenzel (von), Dr.', ' Henry Joachim, Dr. phil., Dr. jur.', ' Kurt, Dr. jur.', ' Walter, Dr. jur.', ' Anton', ' Ladislaus', ' Heinrich', ' Efraim (bis 1938 Spiegel, Hermann)', ' Martin, Dr. jur.', ' Jakob', ' Josef', ' Hermann August Albert', ' Karl (urspr. Naumann, Kurt Wilhelm)', ' Alfred, Dr. jur.', ' Rudolf', ' Ludwig', ' Paul, Dr. jur.', ' Frederick Simon (urspr. Friedrich), Dr. med.', ' Erich Gustav Hinrich', ' Arthur Georg', ' Robert,Dr. med. dent.', ' Richard Joseph, Dr. jur.', ' Walter, Dr. phil.', ' Siegfried', ' Karl', ' Yeshayahu (urspr. Wolfsberg, Oscar), Dr. med.', ' Shimon (urspr. Koch, Simon)', ' Abraham', ' Uri (urspr. Ostermann, Helmut)', ' Ehud', ' Baruch (urspr. Eisenstadt, Boris), Dr.jur.', ' Fritz, Dr. rer. pol.', ' Kurt', ' David Josef, Dr. phil.', ' Ilse, geb. Rosenfeld', ' Kurt', ' Hermann, Dr. jur.', ' Paul', ' Friedrich (Fritz)']
In [39]:
Vorname= [element.strip() for element in Vorname] #Entfernung des Leerzeichens vor dem Vornamen
Vorname = [re.sub(r'\s\([^)]*\)', '', wort) for wort in Vorname] #Entfernung der Zusatzinfo in Klammern bei Vornamen
Vorname = [re.sub(r',.*', '', text) for text in Vorname] # Entfernung der Kommas und Strings nach der Komma
In [40]:
print(Vorname[:50]) # standardisierte Vornamen
['Uriel', 'Alexander', 'Manfred', 'Wilhelm', 'Ellen C.', 'Friedrich Wolfgang', 'Gerson', 'Max Kurt', 'Salomon', 'Alfred', 'Franz Xaver', 'Peter Wenzel', 'Henry Joachim', 'Kurt', 'Walter', 'Anton', 'Ladislaus', 'Heinrich', 'Efraim', 'Martin', 'Jakob', 'Josef', 'Hermann August Albert', 'Karl', 'Alfred', 'Rudolf', 'Ludwig', 'Paul', 'Frederick Simon', 'Erich Gustav Hinrich', 'Arthur Georg', 'Robert', 'Richard Joseph', 'Walter', 'Siegfried', 'Karl', 'Yeshayahu', 'Shimon', 'Abraham', 'Uri', 'Ehud', 'Baruch', 'Fritz', 'Kurt', 'David Josef', 'Ilse', 'Kurt', 'Hermann', 'Paul', 'Friedrich']
In [41]:
df.insert(2, 'Nachname', Nachname) # Nachname als Spalte
df.insert(3, 'Vorname', Vorname) #Vorname als Spalte
In [42]:
HTML(df.iloc[10:20, 1:4].to_html(index=False)) #Ergebnis
Out[42]:
Name | Nachname | Vorname |
---|---|---|
Aenderl, Franz Xaver | Aenderl | Franz Xaver |
Albert, Peter Wenzel (von), Dr. | Albert | Peter Wenzel |
Alexander, Henry Joachim, Dr. phil., Dr. jur. | Alexander | Henry Joachim |
Alexander, Kurt, Dr. jur. | Alexander | Kurt |
Alexander, Walter, Dr. jur. | Alexander | Walter |
Alfons, Anton | Alfons | Anton |
Alliger, Ladislaus | Alliger | Ladislaus |
Allina, Heinrich | Allina | Heinrich |
Alroy, Efraim (bis 1938 Spiegel, Hermann) | Alroy | Efraim |
Alterthum, Martin, Dr. jur. | Alterthum | Martin |
4. Ermittlung des Geschlechts¶
Das Geschlecht der Personen wurde anhand der Vornamen mithilfe des Pakets gender_guesser ermittelt. Da das Paket das Geschlecht nur anhand eines einzigen Vornamens bestimmen kann, wie beispielsweise Anna, aber nicht Anna Maria oder Anna-Maria, mussten zunächst aus der Liste Vorname die ersten Vornamen extrahiert werden. Hierfür wurden aus der Liste die Bindestriche entfernt und durch Leerzeichen ersetzt. Danach wurden die Elemente der Liste nach dem ersten Leerzeichen getrennt und das erste Element [0] in die neue Liste extrahiert.
Da die Ermittlung des Geschlechts der 1434 Personen relativ lange dauert, wurden die Ergebnisse als Liste in einer txt-Datei abgespeichert.
In [45]:
Vorname_for_Gender = [name.replace('-', ' ').replace('.', ' ').replace(',', ' ') for name in Vorname] #Entfernung der
#Bindestriche und vorsichtshalber auch weiteren Satzzeichen
Vorname_for_Gender = [name.split(' ', 1)[0] for name in Vorname_for_Gender] #Abspeicherung des ersten Vornamen in einer Liste
Vorname_for_Gender = [name.replace('(', '').replace(')', '') for name in Vorname_for_Gender] # Entfernung der Klammer in Vornamen
#wie z. B. Arndt, H(einz) W(olfgang)
In [46]:
print(Vorname_for_Gender[:100]) # Ergebnis der Trennung der ersten Vornamen
['Uriel', 'Alexander', 'Manfred', 'Wilhelm', 'Ellen', 'Friedrich', 'Gerson', 'Max', 'Salomon', 'Alfred', 'Franz', 'Peter', 'Henry', 'Kurt', 'Walter', 'Anton', 'Ladislaus', 'Heinrich', 'Efraim', 'Martin', 'Jakob', 'Josef', 'Hermann', 'Karl', 'Alfred', 'Rudolf', 'Ludwig', 'Paul', 'Frederick', 'Erich', 'Arthur', 'Robert', 'Richard', 'Walter', 'Siegfried', 'Karl', 'Yeshayahu', 'Shimon', 'Abraham', 'Uri', 'Ehud', 'Baruch', 'Fritz', 'Kurt', 'David', 'Ilse', 'Kurt', 'Hermann', 'Paul', 'Friedrich', 'Wilhelm', 'Günther', 'Eugen', 'Naftali', 'Abraham', 'Walter', 'Heinrich', 'Ludwig', 'Leo', 'Otto', 'Robert', 'Karl', 'Rupprecht', 'Lilly', 'Karl', 'Karl', 'Fritz', 'Heinrich', 'Karl', 'Karl', 'Ludwig', 'Käthe', 'Rudolf', 'Arno', 'Naftali', 'Walter', 'Kurt', 'Otto', 'Alice', 'Alfred', 'Stefan', 'Adolf', 'Alfred', 'Herzl', 'Kurt', 'Georg', 'Rudolf', 'Paul', 'Gustav', 'Wilhelm', 'Anna', 'Hans', 'Friedrich', 'Jakob', 'Otto', 'Wilhelm', 'Max', 'Hermann', 'Moshe', 'Thomas']
In [47]:
Geschlecht = [] #neue Liste "Geschlecht"
for name in Vorname_for_Gender: #Ermittlung der Gender mit Paket Gender_guesser
d = gender.Detector()
geschlecht = d.get_gender(name)
Geschlecht.append(geschlecht) #Abspeicherung des Geschlechts in Liste "Geschlecht"
In [48]:
datei_Geschlecht = open("Geschlecht.txt", "w", encoding="utf-8") # Abspeicherung in einer txt-Datei
for geschlecht in Geschlecht:
#datei_Geschlecht.write(geschlecht)
#datei_Geschlecht.write("\n")
In [49]:
Gender = open("Gender.txt", "r", encoding="utf-8").read().split("\n")[:-1] #Hochladen der abgespeicherten Liste
In [50]:
element_counts = pd.Series(Gender).value_counts() # unique Elemente der Liste
print(element_counts)
male 1288 female 116 unknown 23 andy 4 mostly_male 3 Name: count, dtype: int64
Das Ergebnis der Ermittlung ist eine neue Liste Gender, die neben eindeutigen Geschlechtszuweisungen wie male und female auch weniger eindeutige Zuweisungen wie mostly_male, mostly_female, andy (steht für androgyn) sowie auch die fehlende Zuweisung unknown enthält.
Die Geschlechtzuweisungen male und female werden ins Deutsche übersetzt, die nicht eindeutigen oder fehlenden Zuweisungen zunächst als unbekannt erfasst. Später können die Angaben manuell verfolständigt werden.
In [52]:
Geschlecht_german = [] #Übersetzung der Geschlechter ins Deutsche
for gender in Gender:
if gender == "male":
Geschlecht_german.append("männlich")
elif gender == "female":
Geschlecht_german.append("weiblich")
else:
Geschlecht_german.append("unbekannt")
In [53]:
print(Geschlecht_german[:50])
['männlich', 'männlich', 'männlich', 'männlich', 'weiblich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'männlich', 'weiblich', 'männlich', 'männlich', 'männlich', 'männlich']
In [54]:
df.insert(4, 'Gender', Geschlecht_german)
In [55]:
HTML(df.iloc[:10, 2:5].to_html(index=False))
Out[55]:
Nachname | Vorname | Gender |
---|---|---|
Abrahamowicz | Uriel | männlich |
Abusch | Alexander | männlich |
Ackermann | Manfred | männlich |
Adam | Wilhelm | männlich |
Adams | Ellen C. | weiblich |
Adler | Friedrich Wolfgang | männlich |
Adler | Gerson | männlich |
Adler | Max Kurt | männlich |
Adler-Rudel | Salomon | männlich |
Adolph | Alfred | männlich |
Nun kann die Geschlechterverteilung beispielsweise mit plotly visualisiert werden.
In [57]:
data_counts = df['Gender'].value_counts().reset_index()
data_counts.columns = ['Gender', 'Häufigkeit']
fig = px.bar(data_counts, x="Gender", y="Häufigkeit", color="Gender", width=800, height=600, text="Häufigkeit",
color_discrete_sequence=['#1f77b4', 'navy', 'darkgrey'], title="Geschlechterverteilung", opacity=0.5)
fig.update_layout(bargap=0.6)
fig.update_traces(textposition='outside')
fig.update_layout(template="plotly_white")
fig.update_traces(
hovertemplate= 'Gender: %{x}<extra></extra><br>' +
'Häufigkeit: %{y}'
)
fig.show()
5. Ermittlung des Geburtsjahres und Sterbejahres¶
Wie bereits erwähnt, befinden sich die Angaben zum Geburtsdatum, Geburtsort sowie ggf. zum Sterbedatum und Sterbeort der Personen in der Spalte Geburtsdatum,-ort/ggf. Sterbedatum,-ort. Die Geburts- und Sterbejahre sollten extrahiert und in zwei neue Spalten abgespeichert werden. Die Analyse der Spalteneinträge zeigte, dass in den meisten Fällen die Angaben zur Geburt der Person nach den Strings b. oder geb. und die Angaben zum Tod der Person nach solchen Strings wie d., gest., g., hinger. oder umgek. vorkommen, wie beispielsweise hier: b. Bucharest, Rum. 5 Oct. 1909, d. Bern 2 Mar. 1960. Zuerst wurde mithilfe regulärer Ausdrücke der Text, der zwischen den geburts- und todbezogenen Strings steht (hier: Bucharest, Rum. 5 Oct. 1909), extrahiert und in der separaten Liste geboren abgespeichert. Falls kein todbezogener String vorkam, was relativ häufig der Fall war, da viele Personen zur Zeit der Verfassung des Lexikons noch lebten, wurde der gesamte nach dem geburtsbezogenen String stehende Text ebenfalls in die Liste geboren extrahiert. Danach wurde der nach dem todbezogenen String stehende Text (hier: Bern 2 Mar. 1960) in der Liste gestorben abgespeichert. Für die Ermittlung des Geburts- und Sterbejahres wurden ebenfalls mit regulären Ausdrücken aus den Listen geboren und gestorben vierstellige Zahlen, die entweder mit 18 oder mit 19 beginnen, extrahiert und in den Listen Geburtsjahr und Sterbejahr abgespeichert.
In [60]:
datum = df["Geburtsdatum,-ort/ggf. Sterbedatum,-ort"].tolist() # Spalte mit Geburts-und Sterbejahren als Liste
In [61]:
print(datum[:20])
['geb. 29. Sept. 1915\xa0 Wien;\xa0', 'geb. 14. Febr. 1902\xa0 Nürnberg;\xa0', 'geb. 1. Nov. 1898\xa0 Nikolsburg/Mähren;\xa0', 'geb. 26. Juli 1905\xa0 Ludenberg b. Düsseldorf;\xa0', 'geb. 1. Mai 1925\xa0 Hannover;\xa0', 'geb. 9. Juli 1879\xa0 Wien,\xa0 gest. 2. Jan. 1960\xa0 Zürich;\xa0', 'geb. 2. Okt. 1927\xa0 Berlin;\xa0', 'geb. 12. Juni 1905\xa0 Pilsen/Böhmen;\xa0', 'geb. 23. Juni 1894\xa0 Czernowitz/Bukowina,\xa0 gest. 14. Nov. 1975\xa0 Jerusalem;\xa0', 'geb. 30. Juli 1895\xa0 Sommerfeld/Niederlausitz,\xa0 gest. 27. Apr. 1959\xa0 Berlin (Ost);\xa0', 'geb. 25. Nov. 1883\xa0 Steinweg b. Regensburg,\xa0 gest. 20. Okt. 1951\xa0 Kulmbach/Oberfr.;\xa0', 'k.A.', 'geb. 4. Jan. 1897;\xa0', 'geb. 13. Aug. 1892\xa0 Krefeld,\xa0 gest. 18. Febr. 1962\xa0 New York;\xa0', 'geb. 20. März 1878\xa0 Berlin,\xa0 gest. 20. Apr. 1949\xa0 New York;\xa0', 'geb. 17. Jan. 1898\xa0 Wampersdorf b. Mödling/Niederösterr.;\xa0', 'geb. 1898 (?),\xa0 gest. 1942\xa0 in GB;\xa0', 'geb. 24. Nov. 1878\xa0 Schaffa/Mähren,\xa0 gest. 10. Dez. 1953\xa0 Wien;\xa0', 'geb. 15. Aug. 1915\xa0 Hamburg;\xa0', 'geb. 31. Aug. 1887\xa0 Bernberg/Saale,\xa0 gest. 12. Febr. 1976\xa0 Tel Aviv;\xa0']
In [62]:
geboren = [] #neue Liste für Strings mit geburtsbezogener Informantion
regex_geboren = re.compile(r'(?:^geb\.|^b\.)\s+(.*?)(?:\bd\.|\bgest\.|\bg\.|\bgef\.|\bumgek\.|\bexecuted|\bdied|\bhinger\.|$)', re.DOTALL)
for satz in datum: # Extrakion der Strings, die zwischen geburts- und sterbebezogenen Strings oder nach geburtsbezogenen Strings stehen
ergebnisse = regex_geboren.findall(satz)
if ergebnisse:
for extrakt in ergebnisse:
geboren.append(extrakt) #Abspeicherung der geburtsbezogenen Strings
else:
geboren.append("")
In [63]:
print(geboren[:20])
['29. Sept. 1915\xa0 Wien;\xa0', '14. Febr. 1902\xa0 Nürnberg;\xa0', '1. Nov. 1898\xa0 Nikolsburg/Mähren;\xa0', '26. Juli 1905\xa0 Ludenberg b. Düsseldorf;\xa0', '1. Mai 1925\xa0 Hannover;\xa0', '9. Juli 1879\xa0 Wien,\xa0 ', '2. Okt. 1927\xa0 Berlin;\xa0', '12. Juni 1905\xa0 Pilsen/Böhmen;\xa0', '23. Juni 1894\xa0 Czernowitz/Bukowina,\xa0 ', '30. Juli 1895\xa0 Sommerfeld/Niederlausitz,\xa0 ', '25. Nov. 1883\xa0 Steinweg b. Regensburg,\xa0 ', '', '4. Jan. 1897;\xa0', '13. Aug. 1892\xa0 Krefeld,\xa0 ', '20. März 1878\xa0 Berlin,\xa0 ', '17. Jan. 1898\xa0 Wampersdorf b. Mödling/Niederösterr.;\xa0', '1898 (?),\xa0 ', '24. Nov. 1878\xa0 Schaffa/Mähren,\xa0 ', '15. Aug. 1915\xa0 Hamburg;\xa0', '31. Aug. 1887\xa0 Bernberg/Saale,\xa0 ']
In [64]:
gestorben = [] #neue Liste für Strings mit sterbebezogener Informantion
regex_gestorben = re.compile(r'(?:\bgest\.|\bg\.|\bd\.|\bexecuted|\bgef\.|\bdied|\bhinger\.|\bgef\.|\bhinger\.)\s+(.*)', re.IGNORECASE)
for satz in datum: # Extraktion der Strings, die nach sterbebezognen Strings stehen
ergebnisse = regex_gestorben.findall(satz)
if ergebnisse:
for extrakt in ergebnisse:
gestorben.append(extrakt) #Abspeicherung der sterbebezogenen Strings
else:
gestorben.append("")
In [65]:
print(gestorben[:20])
['', '', '', '', '', '2. Jan. 1960\xa0 Zürich;\xa0', '', '', '14. Nov. 1975\xa0 Jerusalem;\xa0', '27. Apr. 1959\xa0 Berlin (Ost);\xa0', '20. Okt. 1951\xa0 Kulmbach/Oberfr.;\xa0', '', '', '18. Febr. 1962\xa0 New York;\xa0', '20. Apr. 1949\xa0 New York;\xa0', '', '1942\xa0 in GB;\xa0', '10. Dez. 1953\xa0 Wien;\xa0', '', '12. Febr. 1976\xa0 Tel Aviv;\xa0']
In [66]:
geburtsjahr = [] #neue Liste für Geburtsjahr
for jahr in geboren: #nach Geburtsjahr mit RegEx in Liste "geboren" suchen
matches = re.findall(r"18[0-9][0-9]|19[0-9][0-9]", jahr) #Regex für die Suche nach Jahreszahlen
geburtsjahr.append(matches)
In [67]:
print(geburtsjahr[715:750])
[['1895'], ['1898', '1897'], ['1912'], ['1891'], ['1905'], ['1893'], ['1869'], ['1896'], ['1905'], ['1902'], ['1901'], ['1903'], ['1900'], ['1887'], ['1898'], ['1899'], ['1871'], ['1923'], ['1914'], ['1900'], ['1899'], ['1870'], ['1885'], ['1886'], ['1922'], ['1907'], ['1906'], ['1911'], ['1885'], [], ['1870'], ['1891'], ['1888'], [], ['1920']]
In [68]:
sterbejahr = [] #neue Liste für "Sterbejahr"
for jahr in gestorben: #nach Sterbejahr mit RegEx in Liste "gestorben" suchen
matches = re.findall(r"18[0-9][0-9]|19[0-9][0-9]", jahr) #Regex für die Suche nach Jahreszahlen
sterbejahr.append(matches)
In [69]:
print(sterbejahr[:20])
[[], [], [], [], [], ['1960'], [], [], ['1975'], ['1959'], ['1951'], [], [], ['1962'], ['1949'], [], ['1942'], ['1953'], [], ['1976']]
Die Kontrolle der Ergebnisse zeigte, dass in den Listen geburtsjahr und sterbejahr in manchen Fällen die Jahresangaben fehlen und in manchen Fällen nicht nur eine, sondern zwei Jahreszahlen vorkommen. Dies wurde zum einen dadurch verursacht, dass der todbezogene String nach der Jahreszahl stand, wie beispielsweise 1943 umgek. im Holocaust. So wurden die Sterbejahre zusammen mit den Geburtsjahren in die Spalte Geburtsjahr extrahiert. Ein anderer Grund dafür waren zwei alternative Jahresangaben in den entsprechenden Zeilen, wie beispielsweise b. Cologne 15 Mar. 1908 (Bohemia, 1906 [?]).
Im ersten Fall könnten die Sterbejahre manuell in die Spalte Sterbejahr übertragen werden. Im zweiten Fall kann man nach korrekten Geburts- und Sterbeangaben recherchiert und die Spalteneinträge entsprechend korrigiert. Doch in diesem Projekt werden die Mehrfachnennungen einfachheitshalber in fehlende Werte umgewandelt.
In [71]:
Geburtsjahr = [element[0] if len(element) == 1 else '' for element in geburtsjahr] #neue Liste für Geburtsjahre ohne Klammern
#und ohne mehrmals vorkommenen Jahren
In [72]:
print(Geburtsjahr[715:750])
['1895', '', '1912', '1891', '1905', '1893', '1869', '1896', '1905', '1902', '1901', '1903', '1900', '1887', '1898', '1899', '1871', '1923', '1914', '1900', '1899', '1870', '1885', '1886', '1922', '1907', '1906', '1911', '1885', '', '1870', '1891', '1888', '', '1920']
In [73]:
Sterbejahr = [element[0] if len(element) == 1 else '' for element in sterbejahr]
In [74]:
print(Sterbejahr[:20])
['', '', '', '', '', '1960', '', '', '1975', '1959', '1951', '', '', '1962', '1949', '', '1942', '1953', '', '1976']
In [75]:
df.insert(5, 'Geburtsjahr', Geburtsjahr) # Geburtsjahr zu Spalte
In [76]:
df.insert(6, 'Sterbejahr', Sterbejahr) #Sterbejahr zu Spalte
In [77]:
HTML(df.iloc[:10, 2:7].to_html(index=False))
Out[77]:
Nachname | Vorname | Gender | Geburtsjahr | Sterbejahr |
---|---|---|---|---|
Abrahamowicz | Uriel | männlich | 1915 | |
Abusch | Alexander | männlich | 1902 | |
Ackermann | Manfred | männlich | 1898 | |
Adam | Wilhelm | männlich | 1905 | |
Adams | Ellen C. | weiblich | 1925 | |
Adler | Friedrich Wolfgang | männlich | 1879 | 1960 |
Adler | Gerson | männlich | 1927 | |
Adler | Max Kurt | männlich | 1905 | |
Adler-Rudel | Salomon | männlich | 1894 | 1975 |
Adolph | Alfred | männlich | 1895 | 1959 |
6. Ermittlung des Ausreisealters¶
Die standardisierten Angaben der Geburtsjahre ermöglichen die Ermittlung weiterer für die Untersuchung der Emigration und des Exils relevanten Werte wie z. B. das Ausreisealter. Unter dem Ausreisealter versteht man das Alter der Person zum Zeitpunkt ihrer ersten Ausreise aus Deutschland, Österreich oder der Tschechoslowakei. Für die Ermittlung des Ausreisealters wurden aus den Werten der Spalte Zieljahr1 (Jahr der ersten Ausreise) die Werte der Spalte Geburtsjahr abgezogen. Die Ergebnisse werden in der neuen Spalte Ausreisealter abgespeichert.
In [80]:
Ausreisejahr = df["Zieljahr1"].tolist() #Spalte Zieljahr1 (Jahr der ersten Ausreise) zu Liste
Geburtsjahr = df["Geburtsjahr"].tolist() #Spalte Geburtsjahr zu Liste
In [81]:
datentypen = [type(wert) for wert in Ausreisejahr]
print(datentypen[:20])
[<class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>]
In [82]:
datentypen = [type(wert) for wert in Geburtsjahr] # Geburtsjahre sind als Strings abgespeichert
#und sollen zunächst in Floats umgewandelt werden
print(datentypen[:20])
[<class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>, <class 'str'>]
In [83]:
Geburtsjahr = [float(x) if x else np.nan for x in Geburtsjahr] # String zu Float
datentypen = [type(wert) for wert in Geburtsjahr]
print(datentypen[:20])
[<class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>, <class 'float'>]
In [84]:
ergebnis = [] #neue Liste für Ausreisealter
for wert_a, wert_b in zip(Ausreisejahr, Geburtsjahr): #Aus dem Ausreisejahr das Geburtsjahr abziehen
ergebnis.append(wert_a - wert_b)
In [85]:
print(ergebnis[:20])
[19.0, 31.0, 40.0, 28.0, 14.0, 56.0, 12.0, 33.0, 42.0, 38.0, 51.0, nan, nan, 47.0, 61.0, 40.0, 40.0, 61.0, 18.0, 51.0]
In [86]:
df.insert(7, 'Ausreisealter', ergebnis) # neue Spalte "Ausreisealter" hinzufügen
In [87]:
HTML(df.iloc[:10, 2:8].to_html(index=False))
Out[87]:
Nachname | Vorname | Gender | Geburtsjahr | Sterbejahr | Ausreisealter |
---|---|---|---|---|---|
Abrahamowicz | Uriel | männlich | 1915 | 19.0 | |
Abusch | Alexander | männlich | 1902 | 31.0 | |
Ackermann | Manfred | männlich | 1898 | 40.0 | |
Adam | Wilhelm | männlich | 1905 | 28.0 | |
Adams | Ellen C. | weiblich | 1925 | 14.0 | |
Adler | Friedrich Wolfgang | männlich | 1879 | 1960 | 56.0 |
Adler | Gerson | männlich | 1927 | 12.0 | |
Adler | Max Kurt | männlich | 1905 | 33.0 | |
Adler-Rudel | Salomon | männlich | 1894 | 1975 | 42.0 |
Adolph | Alfred | männlich | 1895 | 1959 | 38.0 |
Nun kann auch das Ausreisealter der Personen sowie die Häufigkeit der ersten Ausreisen pro Jahr visualisiert werden.
In [89]:
alter_counts = df['Ausreisealter'].value_counts().sort_index()
custom_colorscale = ['lightblue', '#2874a6']
fig = px.bar(alter_counts, x= alter_counts.index, y = alter_counts.values, width=850, height=650, color = alter_counts.values,
title = "Ausreisealter",
color_continuous_scale=custom_colorscale, opacity=0.8)
fig.update_layout(
xaxis_title='Ausreisealter', # Manuelle Benennung der x-Achse
yaxis_title='Häufigkeit'
)
fig.update_traces(
hovertemplate="Ausreisealter: %{x}<br>Häufigkeit: %{y}"
)
fig.update_xaxes(dtick=5)
fig.update_layout(template="plotly_white")
fig.show()
In [90]:
year_counts = df['Zieljahr1'].value_counts().sort_index()
year_counts = year_counts[(year_counts.index >= 1933) & (year_counts.index <= 1940)]
fig = px.bar(year_counts, x= year_counts.index, y = year_counts.values, width=850, height=650, color = year_counts.values,
title = "Ausreisen pro Jahr",
color_continuous_scale=[[0, 'steelblue'], [1, 'navy']], opacity=0.7)
fig.update_traces(textposition='outside')
fig.update_layout(bargap=0.1)
fig.update_layout(
xaxis_title='Ausreisejahr', # Manuelle Benennung der x-Achse
yaxis_title='Häufigkeit'
)
fig.update_traces(
hovertemplate="Ausreisejahr: %{x}<br>Häufigkeit: %{y}"
)
fig.update_layout(template="plotly_white")
fig.show()
7. Ermittlung der Anzahl der Zielorte¶
Ein weiterer für die Untersuchung der Emigration relevanter Wert ist Anzahl der Zielorte. Für die Ermittlung dieses Wertes wurden alle 14 Zielort-Spalten in einem neuen Data Frame df_land zusammengefügt. Die meisten Zeilen der Spalten sind nicht vollständig ausgefüllt, da nur relativ wenige Personen mehr als drei Mal die Zielländer gewechselt haben. Für die Ermittlung der Anzahl der Zielländer wurde zunächst die Anzahl der fehlenden Werte pro Zeile ermittelt. Danach wurde dieser Wert von der Gesamtanzahl der Spalten (also 14) abgezogen.
In [93]:
df_land = df[['Zielort1', 'Zielort2', 'Zielort3', 'Zielort4',
'Zielort5', 'Zielort6', 'Zielort7', 'Zielort8', 'Zielort9',
'Zielort10', 'Zielort11', 'Zielort12', 'Zielort13', 'Zielort14']]
In [94]:
fehlende_werte = df_land.isnull() # Ermittlung der fehlenden und nicht fehlenden Werte
print(fehlende_werte[:5])
Zielort1 Zielort2 Zielort3 Zielort4 Zielort5 Zielort6 Zielort7 \ 12 False True True True True True True 17 False False False False False True True 20 False False False False True True True 25 False False False False True True True 26 False False True True True True True Zielort8 Zielort9 Zielort10 Zielort11 Zielort12 Zielort13 Zielort14 12 True True True True True True True 17 True True True True True True True 20 True True True True True True True 25 True True True True True True True 26 True True True True True True True
In [95]:
anzahl_einträge = df_land.shape[1] - fehlende_werte.sum(axis=1) # Anzahl der Spalten minus Summe der fehlenden Werte
#pro Zeile
print(anzahl_einträge[:10])
12 1 17 5 20 4 25 4 26 2 42 4 43 1 58 1 63 2 65 7 dtype: int64
In [96]:
liste = anzahl_einträge.tolist()
df.insert(11, 'Anzahl_Zielorte', liste) # neue Spalte "Anzahl_Zielorte hinzufügen
In [97]:
HTML(df.iloc[:10, 11:25].to_html(index=False)) # neue Spalte "Anzahl_Zielorte hinzufügen
Out[97]:
Anzahl_Zielorte | Zieljahr1 | Zielort1 | Zieljahr2 | Zielort2 | Zieljahr3 | Zielort3 | Zieljahr4 | Zielort4 | Zieljahr5 | Zielort5 | Zieljahr6 | Zielort6 | Zieljahr7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1934.0 | Palestine | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
5 | 1933.0 | Saarbrücken | 1935.0 | Prag | 1937.0 | France | 1941.0 | Mexiko | 1946.0 | Berlin | NaN | NaN | NaN |
4 | 1938.0 | Belgien | 1938.0 | Frankreich | 1940.0 | USA | 1964.0 | Österreich | NaN | NaN | NaN | NaN | NaN |
4 | 1933.0 | Saarbrücken | 1933.0 | France | 1934.0 | Denmark | 1945.0 | Berlin | NaN | NaN | NaN | NaN | NaN |
2 | 1939.0 | UK | 1948.0 | Canada | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
4 | 1935.0 | Belgien | 1940.0 | France | 1940.0 | USA | 1946.0 | CH | NaN | NaN | NaN | NaN | NaN |
1 | 1939.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | 1938.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
2 | 1936.0 | UK | 1949.0 | Israel | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7 | 1933.0 | Prag | 1933.0 | Moskau | 1933.0 | NL | 1933.0 | France | 1938.0 | CH | 1939.0 | France | 1946.0 |
Zum Schluss erfolgt die Visualisierung der Verteilung des ermittelten Wertes Anzahl Zielorte.
In [99]:
places_counts = df['Anzahl_Zielorte'].value_counts().sort_index()
custom_colorscale = ['navy', 'lightblue']
fig = px.bar(places_counts, x= places_counts.index, y = places_counts.values, width=850, height=650, color = places_counts.values,
title = "Anzahl der Zielorte",
color_continuous_scale=custom_colorscale, opacity=0.7)
fig.update_traces(textposition='outside')
fig.update_layout(bargap=0.1)
fig.update_layout(
xaxis_title='Anzahl Zielorte', # Manuelle Benennung der x-Achse
yaxis_title='Häufigkeit'
)
fig.update_layout(template="plotly_white")
fig.update_xaxes(dtick=1)
fig.update_traces(
hovertemplate="Anzahl Zielorte: %{x}<br>Häufigkeit: %{y}"
)
fig.show()
8. Standardisierung der Länder¶
Wie auch viele andere Angaben der Tabelle weisen die Zielortangaben, die in den Spalten Zielort1 bis Zielort14 enthalten sind, sprachliche Uneinheitlichkeit auf. Außerdem wurden manchmal vollständige Ländernamen, manchmal entsprechende Abkürzungen wie z.B. UK, CH oder USA und manchmal Stadtnamen eingetragen. Mit der Standardisierung der Zielländer-Spalten sollte erreicht werden, dass die Ländernamen standardisiert und Stadtnamen durch die entsprechenden, ebenfalls standardisierten Ländernamen ersetzt werden. Anschließend sollten alle Ländernamen in das Deutsche übersetzt werden.
Die Standardisierung erfolge mithilfe der geographischen Datenbank GeoNames und des Python-Paket requests. Mit diesem Paket ist es möglich, Webseiten abzufragen. So werden die Angaben der Zielort-Spalten nacheinander in die Suchmaschine der Datenbank "geschickt". Danach ist es möglich, den HTML-Text der jeweiligen Ergebnisseiten automatsch zu durchsuchen. In diesem Projekt wird beispielsweise nur eine Spalte Zieljahr1 standardisiert. Der Ergebnis der Abfrage der Datenbank ist eine Liste mit standardisierten Ländercode.
In [102]:
HTML(df.iloc[:10, 12:26].to_html(index=False))
Out[102]:
Zieljahr1 | Zielort1 | Zieljahr2 | Zielort2 | Zieljahr3 | Zielort3 | Zieljahr4 | Zielort4 | Zieljahr5 | Zielort5 | Zieljahr6 | Zielort6 | Zieljahr7 | Zielort7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1934.0 | Palestine | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | Saarbrücken | 1935.0 | Prag | 1937.0 | France | 1941.0 | Mexiko | 1946.0 | Berlin | NaN | NaN | NaN | NaN |
1938.0 | Belgien | 1938.0 | Frankreich | 1940.0 | USA | 1964.0 | Österreich | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | Saarbrücken | 1933.0 | France | 1934.0 | Denmark | 1945.0 | Berlin | NaN | NaN | NaN | NaN | NaN | NaN |
1939.0 | UK | 1948.0 | Canada | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1935.0 | Belgien | 1940.0 | France | 1940.0 | USA | 1946.0 | CH | NaN | NaN | NaN | NaN | NaN | NaN |
1939.0 | USA | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1938.0 | UK | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1936.0 | UK | 1949.0 | Israel | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1933.0 | Prag | 1933.0 | Moskau | 1933.0 | NL | 1933.0 | France | 1938.0 | CH | 1939.0 | France | 1946.0 | Deutschland |
Wie man oben sieht, befindet sich zwischen den standardisierten Zielländern die Stadt Saarbrücken. Das Programm wird die Stadt dem Land Deutschland zuweisen, was aus der heutigen Perspektive auch korrekt ist. Jedoch wurde das Saargebiet und mit ihm auch die Stadt Saarbrücken nach dem Ersten Weltkrieg unter die Verwaltung des Völkerbundes gestellt. Erst 1935 wurde Saargebiet an das Deutsche Reich angegliedert. Dies wird im Coode entsprechend berücksichtigt.
In [104]:
Zielort = df["Zielort1"].tolist() # Spalte "Zielort1" als Liste
Zielort = list(map(str, Zielort)) # Liste als String-Liste
datei_Ziel1 = open("Zielort1.txt", "w", encoding="utf-8") # Öffnen der Datei für Abspeicherung der Ergebnisse
country_list = [] # neue Liste für Länder-Codes
for city in Zielort:
# die Werte der Zeile werden nacheinander in die Suchseite der GeoNames-Datenbank geschickt
response = requests.request("GET", f"https://www.geonames.org/search.html?q={city}&country=")
ergebnis = re.findall(r"/countries.*\.html", response.text) # auf der Ergebnis-Seite wird Spalte Countries gefunden
if city == "nan":
country_list.append("")
elif city == "Saarbrücken":
country_list.append("Saarbrücken")
elif ergebnis:
# dem ersten Ergebnis in der Spalte Countries [0] wird ein ".html"-String abgetrennt
# Danach wird der Länder-Code an der Stelle [-2] gefunden
country_code = ergebnis[0].strip(".html").split("/")[-2]
country_list.append(country_code)
else:
#country_list.append("")
for country in country_list: # Länder-Coden werden in einer txt-Datei abgespeichert
datei_Ziel1.write(country)
datei_Ziel1.write("\n")
datei_Ziel1.close()
In [105]:
Zielland1 = open("Zielort1.txt", "r", encoding="utf-8").read().split("\n")[:-1]
print(Zielland1[:100])
['PS', 'Saarbrücken', 'BE', 'Saarbrücken', 'GB', 'BE', 'US', 'GB', 'GB', 'CZ', 'CZ', 'GB', 'GB', 'GB', 'FR', 'NO', 'GB', 'GB', 'PS', 'PS', 'FR', 'PL', 'DK', 'CZ', 'FR', 'RU', 'RU', 'PS', 'FR', 'SX', 'CZ', 'PS', 'GB', 'SX', 'FR', 'GB', 'PS', 'PS', 'GB', 'PS', 'PS', 'PS', 'TR', 'GB', 'GB', 'US', 'FR', 'PS', 'CZ', 'FR', 'RU', 'AR', 'CN', 'PS', 'SX', 'CZ', 'FR', 'PS', 'CZ', 'IT', 'LU', 'GB', 'IT', 'AT', 'BE', 'SE', 'RS', 'Saarbrücken', 'CZ', 'SX', 'SX', 'GB', 'GB', 'CZ', 'PS', 'CZ', 'GB', 'RU', 'AU', 'FR', 'SE', 'FR', 'PS', 'PS', 'PE', 'DK', 'RU', 'FR', 'GB', 'Saarbrücken', 'BE', 'PS', 'EC', 'IT', 'FR', 'CZ', 'US', 'ZA', 'PS', 'FR']
Anschließend werden die standardisierten Ländercodes mithilfe der Dictionaries des Packets GeonamesCache in Ländernamen (auf Englisch) umgewandelt.
In [107]:
gc = geonamescache.GeonamesCache() #mithilfe der Dictionaries werden vollständigen Namen der Länder ermittelt
countries = gc.get_countries()
country_names = []
for land_code in Zielland1:
if land_code == "":
country_names.append("")
elif land_code == "Saarbrücken":
country_names.append("Saarbrücken")
elif land_code in countries:
country_names.append(countries[land_code]['name'])
else:
country_names.append("")
In [108]:
land_namen=country_names
In [109]:
unique_liste = list(set(land_namen)) #unique Liste
unique_liste = list(map(str, unique_liste)) #unique Liste als String
unique_liste = [word for word in unique_liste if word != ''] #Entfernung fehlender Werte
print(unique_liste)
['Trinidad and Tobago', 'France', 'Luxembourg', 'New Zealand', 'China', 'United Kingdom', 'United States', 'Mexico', 'Palestinian Territory', 'Bolivia', 'Austria', 'Belgium', 'Turkey', 'Sweden', 'Serbia', 'Argentina', 'Russia', 'Cuba', 'Kyrgyzstan', 'Norway', 'Sint Maarten', 'Canada', 'Paraguay', 'Peru', 'Germany', 'Chile', 'Netherlands', 'Saarbrücken', 'Finland', 'Colombia', 'Latvia', 'Czechia', 'Australia', 'Poland', 'South Africa', 'Morocco', 'Uruguay', 'Brazil', 'Hungary', 'Denmark', 'Ecuador', 'Spain', 'Italy', 'Egypt']
Die Untersuchung der Ergebnisse zeigt, dass die Datenbank Geonames die Abkürzung NL in der Spalte Zielland1 nicht als Netherlands sondern als Sint Maarten interpretiert hat. Dies wird dann entsprechend korrigiert.
In [111]:
unique_liste.remove("Sint Maarten") # Entfernung aus der unique liste
country_names = ["Netherlands" if city == "Sint Maarten" else city for city in country_names] # Ersetzung in der Ergebnisliste durch Netherlans
In [112]:
print(unique_liste)
['Trinidad and Tobago', 'France', 'Luxembourg', 'New Zealand', 'China', 'United Kingdom', 'United States', 'Mexico', 'Palestinian Territory', 'Bolivia', 'Austria', 'Belgium', 'Turkey', 'Sweden', 'Serbia', 'Argentina', 'Russia', 'Cuba', 'Kyrgyzstan', 'Norway', 'Canada', 'Paraguay', 'Peru', 'Germany', 'Chile', 'Netherlands', 'Saarbrücken', 'Finland', 'Colombia', 'Latvia', 'Czechia', 'Australia', 'Poland', 'South Africa', 'Morocco', 'Uruguay', 'Brazil', 'Hungary', 'Denmark', 'Ecuador', 'Spain', 'Italy', 'Egypt']
Nun sollen die Koordinaten der Länder ermittelt werden, um eine Geovisualisirung der Daten zu ermöglichen. Die Koordinaten werden anhand der Koordinaten der Hauptstädte der jeweiligien Zielländer festgelegt. Die Hauptstädte der Länder werden über den bereits erwähnten Dictionary aus dem Paket geonamescache gefunden. Anschließend wurden mithilfe des Pakets geopy die Koordinaten der Städte ermittelt. Die Länder und deren Koordinaten wurden in einer neuen Excel-Tabelle Koordinaten abgespeichert.
In [114]:
capitals = [] # neue Liste für Hauptstädte
gc = GeonamesCache() # Ermittlung der Hauptstädte mithilfe der GeoName-Datenbank
for country in unique_liste:
if country == "Saarbrücken":
capitals.append("Saarbrücken")
else:
country_info = gc.get_countries_by_names().get(country)
if country_info:
capital = country_info.get("capital")
capitals.append(capital)
else:
capitals.append("")
In [115]:
print(capitals)
['Port of Spain', 'Paris', 'Luxembourg', 'Wellington', 'Beijing', 'London', 'Washington', 'Mexico City', 'East Jerusalem', 'Sucre', 'Vienna', 'Brussels', 'Ankara', 'Stockholm', 'Belgrade', 'Buenos Aires', 'Moscow', 'Havana', 'Bishkek', 'Oslo', 'Ottawa', 'Asuncion', 'Lima', 'Berlin', 'Santiago', 'Amsterdam', 'Saarbrücken', 'Helsinki', 'Bogota', 'Riga', 'Prague', 'Canberra', 'Warsaw', 'Pretoria', 'Rabat', 'Montevideo', 'Brasilia', 'Budapest', 'Copenhagen', 'Quito', 'Madrid', 'Rome', 'Cairo']
In [116]:
capitals = ["Jerusalem" if capital == "East Jerusalem" else capital for capital in capitals]
print(capitals)
['Port of Spain', 'Paris', 'Luxembourg', 'Wellington', 'Beijing', 'London', 'Washington', 'Mexico City', 'Jerusalem', 'Sucre', 'Vienna', 'Brussels', 'Ankara', 'Stockholm', 'Belgrade', 'Buenos Aires', 'Moscow', 'Havana', 'Bishkek', 'Oslo', 'Ottawa', 'Asuncion', 'Lima', 'Berlin', 'Santiago', 'Amsterdam', 'Saarbrücken', 'Helsinki', 'Bogota', 'Riga', 'Prague', 'Canberra', 'Warsaw', 'Pretoria', 'Rabat', 'Montevideo', 'Brasilia', 'Budapest', 'Copenhagen', 'Quito', 'Madrid', 'Rome', 'Cairo']
In [117]:
df_koord = pd.DataFrame({'Land': unique_liste , 'Stadt': capitals})
print(df_koord[:20])
Land Stadt 0 Trinidad and Tobago Port of Spain 1 France Paris 2 Luxembourg Luxembourg 3 New Zealand Wellington 4 China Beijing 5 United Kingdom London 6 United States Washington 7 Mexico Mexico City 8 Palestinian Territory Jerusalem 9 Bolivia Sucre 10 Austria Vienna 11 Belgium Brussels 12 Turkey Ankara 13 Sweden Stockholm 14 Serbia Belgrade 15 Argentina Buenos Aires 16 Russia Moscow 17 Cuba Havana 18 Kyrgyzstan Bishkek 19 Norway Oslo
In [118]:
Capitals = df_koord["Stadt"].tolist() #Spalte Hauptstädte als Liste
geolocator = Nominatim(user_agent="my_geocoder", timeout=10) #Ermittlung der Koordinaten der Hauptstädte mit Paket Nominatim
lat = [] #neue Liste für Latitude
lon = [] #neue Liste für Longitude
for capital in Capitals:
location = geolocator.geocode(capital)
if location:
lat.append(location.latitude)
lon.append(location.longitude)
else:
lat.append('')
lon.append('')
df_koord["lat"] = lat # Latitude-Spalte wird dem Data Frame "Koordinaten" hinzugefügt
df_koord["lon"] = lon #Longitude wird dem Data Frame "Koordinaten" hinzugefügt
df_koord.to_excel("Koordinaten.xlsx")
In [119]:
df_koord=pd.read_excel("Koordinaten.xlsx")
print(df_koord[:20])
Land Stadt lat lon 0 Trinidad and Tobago Port of Spain 10.657268 -61.518017 1 Denmark Copenhagen 55.686724 12.570072 2 Czechia Prague 50.059629 14.446459 3 Canada Ottawa 45.420878 -75.690111 4 United Kingdom London 51.489334 -0.144055 5 Latvia Riga 56.949398 24.105185 6 Norway Oslo 59.913330 10.738970 7 China Beijing 39.905714 116.391297 8 Spain Madrid 40.416705 -3.703582 9 Austria Vienna 48.208354 16.372504 10 Brazil Brasilia -10.333333 -53.200000 11 Uruguay Montevideo -34.905892 -56.191310 12 Luxembourg Luxembourg 49.611277 6.129799 13 Australia Canberra -35.297591 149.101268 14 New Zealand Wellington -41.288795 174.777211 15 Hungary Budapest 47.497879 19.040238 16 France Paris 48.853495 2.348391 17 Mexico Mexico City 19.432630 -99.133178 18 United States Washington 38.895037 -77.036543 19 Palestinian Territory Jerusalem 31.788472 35.218794
Im nächsten Schritt werden die Ländernamen in das Deutsche übersetzt. Da die automatischen Übersetzungen von großen Datenmengen sehr lange dauern, wurde auf die Übersetzung der gesamten Spalte verzichtet. Stattdessen wird die oben bereits erstellte unique_liste, die 42 einzigartige Ländernamen enthält, mithilfe des Pakets translate übersetzt und als Dictionary mit ursprünglichen englischen Ländernamen und entsprechenden deutschen Übersetzungen abgespeichert. Danach wird mit dem Dictionary die gesamte Zielland1-Spalte übersetzt.
In [121]:
translator = Translator(to_lang="German") #Übersetzung der unique_liste ins Deutsche mit dem Paket Translator
word_dict = {} #eues Wörterbuch für Länder auf Englisch und auf Deutsch
for word in unique_liste:
translated_word = translator.translate(word)
word_dict[word] = translated_word #dem Dictionary werden die Ergebnisse der Übersetzung hinzugefügt
with open('land_dict.txt', 'w') as file: # neue txt-Datei für Dictionary
for eng_word, de_word in word_dict.items():
file.write(f"{eng_word}\t{de_word}\n") # Abspeicherung der Dictionary
In [122]:
word_dict = {} #neuer Dictionary
with open('land_dict.txt', 'r') as file:
for line in file:
eng_word, de_word = line.strip().split('\t')
word_dict[eng_word] = de_word #dem Dictionary werden die englische und deutsche Wörter hinzugefügt
translated_words = [] #neue Liste für übersetzte Länder
for word in country_names: #Übersetzung der Spalte mit Dictionary
if word in word_dict:
translated_words.append(word_dict[word])
else:
translated_words.append("")
In [123]:
print(translated_words[:20])
['Palästina', 'Saarbrücken', 'Belgien', 'Saarbrücken', 'Vereinigtes Königreich', 'Belgien', 'Vereinigte Staaten', 'Vereinigtes Königreich', 'Vereinigtes Königreich', 'Tschechien', 'Tschechien', 'Vereinigtes Königreich', 'Vereinigtes Königreich', 'Vereinigtes Königreich', 'Frankreich', 'Norwegen', 'Vereinigtes Königreich', 'Vereinigtes Königreich', 'Palästina', 'Palästina']
In [124]:
Land=df_koord['Land'].tolist()
übersetzte_länder = [] #neue Liste für übersetzte Länder
for land in Land: #Übersetzung der Spalte mit Dictionary
if land in word_dict:
übersetzte_länder.append(word_dict[land])
else:
übersetzte_länder.append("")
print(übersetzte_länder)
['Trinidad und Tobago', 'Dänemark', 'Tschechien', 'Kanada', 'Vereinigtes Königreich', 'Lettland', 'Norwegen', 'China', 'Spanien', 'Österreich', 'Brasilien', 'Uruguay', 'Luxemburg', 'Australien', 'Neuseeland', 'Ungarn', 'Frankreich', 'Mexiko', 'Vereinigte Staaten', 'Palästina', 'Argentinien', 'Marokko', 'Belgien', 'Paraguay', 'Finnland', 'Ekuador', 'Saarbrücken', 'Kuba', 'Südafrika', 'Türkei', 'Kirgisistan', 'Deutschland', 'Polen', 'Chile', 'Kolumbien', 'Serbien', 'Ägypten', 'Peru', 'Bolivien', 'Schweden', 'Niederlande', 'Russland', 'Italien']
Nach der Übersetzung der Spalte werden einige Korrekturen vorgenommen: Namen wie Vereinigtes Königreich oder Vereinigte Staaten werden abgekürzt, Länder wie Russland oder Tschechien werden in Sowjet Union und Tschechoslowakei umbenannt, um die historischen Veränderungen der politischen Grenzen zu berücksichtigen.
In [126]:
ersetzungen = {
"Vereinigtes Königreich": "UK",
"Vereinigte Staaten": "USA",
"Tschechien": "Tschechoslowakei",
"Russland": "Sowjet Union"
}
translated_words = [ersetzungen.get(ort, ort) for ort in translated_words]
print(translated_words[:20])
['Palästina', 'Saarbrücken', 'Belgien', 'Saarbrücken', 'UK', 'Belgien', 'USA', 'UK', 'UK', 'Tschechoslowakei', 'Tschechoslowakei', 'UK', 'UK', 'UK', 'Frankreich', 'Norwegen', 'UK', 'UK', 'Palästina', 'Palästina']
In [127]:
übersetzte_länder = [ersetzungen.get(ort, ort) for ort in übersetzte_länder]
In [128]:
df_koord.insert(2, 'Land_german', übersetzte_länder)
In [129]:
print(df_koord[:10])
Land Stadt Land_german lat \ 0 Trinidad and Tobago Port of Spain Trinidad und Tobago 10.657268 1 Denmark Copenhagen Dänemark 55.686724 2 Czechia Prague Tschechoslowakei 50.059629 3 Canada Ottawa Kanada 45.420878 4 United Kingdom London UK 51.489334 5 Latvia Riga Lettland 56.949398 6 Norway Oslo Norwegen 59.913330 7 China Beijing China 39.905714 8 Spain Madrid Spanien 40.416705 9 Austria Vienna Österreich 48.208354 lon 0 -61.518017 1 12.570072 2 14.446459 3 -75.690111 4 -0.144055 5 24.105185 6 10.738970 7 116.391297 8 -3.703582 9 16.372504
In [130]:
df.insert(14, 'Zielland1_german', translated_words) # neue Spalte "Zielland1_german" hinzufügen
In [131]:
HTML(df.iloc[:20, 12:20].to_html(index=False))
Out[131]:
Zieljahr1 | Zielort1 | Zielland1_german | Zieljahr2 | Zielort2 | Zieljahr3 | Zielort3 | Zieljahr4 |
---|---|---|---|---|---|---|---|
1934.0 | Palestine | Palästina | NaN | NaN | NaN | NaN | NaN |
1933.0 | Saarbrücken | Saarbrücken | 1935.0 | Prag | 1937.0 | France | 1941.0 |
1938.0 | Belgien | Belgien | 1938.0 | Frankreich | 1940.0 | USA | 1964.0 |
1933.0 | Saarbrücken | Saarbrücken | 1933.0 | France | 1934.0 | Denmark | 1945.0 |
1939.0 | UK | UK | 1948.0 | Canada | NaN | NaN | NaN |
1935.0 | Belgien | Belgien | 1940.0 | France | 1940.0 | USA | 1946.0 |
1939.0 | USA | USA | NaN | NaN | NaN | NaN | NaN |
1938.0 | UK | UK | NaN | NaN | NaN | NaN | NaN |
1936.0 | UK | UK | 1949.0 | Israel | NaN | NaN | NaN |
1933.0 | Prag | Tschechoslowakei | 1933.0 | Moskau | 1933.0 | NL | 1933.0 |
1934.0 | Prag | Tschechoslowakei | 1938.0 | Poland | 1938.0 | Denmark | 1938.0 |
NaN | UK | UK | NaN | NaN | NaN | NaN | NaN |
NaN | UK | UK | NaN | NaN | NaN | NaN | NaN |
1939.0 | UK | UK | 1949.0 | USA | NaN | NaN | NaN |
1939.0 | France | Frankreich | NaN | USA | NaN | NaN | NaN |
1938.0 | Norwegen | Norwegen | 1938.0 | Schweden | 1946.0 | Österreich | NaN |
1938.0 | UK | UK | NaN | NaN | NaN | NaN | NaN |
1939.0 | UK | UK | 1949.0 | Österreich | NaN | NaN | NaN |
1933.0 | Palestine | Palästina | NaN | NaN | NaN | NaN | NaN |
1938.0 | Palestine | Palästina | NaN | NaN | NaN | NaN | NaN |
Anschließend wurde die Spalte mit den standardisierten Ländernamen bei Berücksichtigung des Ausreisejahres visualisiert.
Mit bar_polar-Plot wird die Anreisehäufigkeit der 11 am meisten angereisten (mehr als 5 Anreisen) Zielländer im Jahr 1933 angezeigt.
Mit bar_polar-Plot wird die Anreisehäufigkeit der 11 am meisten angereisten (mehr als 5 Anreisen) Zielländer im Jahr 1933 angezeigt.
In [133]:
df_1933 = df[df['Zieljahr1'] == 1933]['Zielland1_german'].value_counts().reset_index() # Erstellung der Tabelle mit Einreisehäufigkeit
#der einzelnen Zielländer im Jahr 1933 für Visualisierung mit bar_polar
In [134]:
df_1933.columns = ['Land_german', 'Anzahl_Einreisen']
In [135]:
print(df_1933[:10])
Land_german Anzahl_Einreisen 0 Tschechoslowakei 112 1 Frankreich 73 2 China 50 3 Saarbrücken 47 4 Niederlande 46 5 Palästina 41 6 Sowjet Union 39 7 Dänemark 24 8 UK 19 9 Österreich 18
In [136]:
fig = px.bar_polar(df_1933[:11], r="Anzahl_Einreisen", theta = "Land_german", title = "Zielländer 1933",
color = "Anzahl_Einreisen",
color_continuous_scale=[
(0, "rgba(0, 0, 139, 0.6)"),
(0.5, "rgba(255, 255, 255, 1)"),
(1, "rgba(139, 0, 0, 0.6)")
])
fig.update_layout(width=830, height=600)
fig.update_layout(
coloraxis_colorbar=dict(
title="Anzahl der Einreisen"
)
)
fig.update_traces(
hovertemplate="<b>%{theta}</b><br>Häufigkeit: %{r}"
)
fig.show()
Mit density_heatmap wird die Häufigkeit der Einreisen pro Jahr angezeigt. Die Jahre mit wenigen Einreisen werden ausgeschlossen. Angezeigt werden nur die Länder mit 20 oder mehr Einreisen.
In [138]:
df_filtered = df[(df['Zieljahr1'] >= 1933) & (df['Zieljahr1'] <= 1939)] # Ausschluss der Jahre mit wenigen Einreisen
country_counts = df_filtered['Zielland1_german'].value_counts() # Ermittlung der Häufigkeit der Einreisen in einzelne Länder
countries_to_keep = country_counts[country_counts >= 20].index
df_filtered = df_filtered[df_filtered['Zielland1_german'].isin(countries_to_keep)] # Ausschluss der Länder, die weniger als 20 mal eingereist wurden
In [139]:
custom_colorscale = [
(0, "rgba(0, 0, 139, 0.6)"),
(0.5, "rgba(255, 255, 255, 1)"),
(1, "rgba(139, 0, 0, 0.6)")
]
fig = px.density_heatmap(df_filtered, x="Zieljahr1", y="Zielland1_german", marginal_y="histogram", color_continuous_scale=custom_colorscale,
title = "Heatmap für Ausreisejahre und Ziellander")
fig.update_layout(width=800, height=500)
fig.update_traces(marker_color="lightblue", selector=dict(type="histogram"))
fig.update_layout(
xaxis_title='Jahr der ersten Ausreise',
yaxis_title='Zielländer'
)
fig.update_traces(hovertemplate= '<b>%{y}</b><br>' +
'Jahr: %{x}<br>' +
'Häufigkeit: %{z}')
fig.update_traces(
hovertemplate='<b>%{y}</b><br>Häufigkeit: %{x}',
selector=dict(type='histogram')
)
fig.update_xaxes(dtick=1)
fig.show()
Mit scatter_geo sollen alle Zielländer nach 1933 visualisiert werden. Dafür soll der Data Frame Koordinaten mit dem Data Frame df_all zusammengeführt werden. df_all enthält nach Ausreisejahren gruppierte Einreisehäufigkeiten.
In [141]:
df_all = df.groupby(['Zieljahr1', 'Zielland1_german']).size().reset_index(name='Häufigkeit') # Erstellung der Tabelle mit
#Einreisehäufigkeiten der einzelnen Zielländer gruppiert nach Einreisejahr
df_all = df_all[(df_all['Zieljahr1'] >= 1933)] # Berücksichtigung aller Jahre nach 1933
df_all.replace('', np.nan, inplace=True)
df_all = df_all.dropna() # Entfernung der fehlenden Werte
print(df_all[:20])
Zieljahr1 Zielland1_german Häufigkeit 9 1933.0 Belgien 7 10 1933.0 Brasilien 1 11 1933.0 China 50 12 1933.0 Dänemark 24 13 1933.0 Frankreich 73 14 1933.0 Kirgisistan 1 15 1933.0 Lettland 3 16 1933.0 Luxemburg 1 17 1933.0 Marokko 1 18 1933.0 Niederlande 46 19 1933.0 Norwegen 2 20 1933.0 Palästina 41 21 1933.0 Polen 2 22 1933.0 Saarbrücken 47 23 1933.0 Schweden 4 24 1933.0 Sowjet Union 39 25 1933.0 Spanien 4 26 1933.0 Südafrika 4 27 1933.0 Tschechoslowakei 112 28 1933.0 UK 19
In [142]:
print(df_all.columns)
Index(['Zieljahr1', 'Zielland1_german', 'Häufigkeit'], dtype='object')
In [143]:
print(df_koord.columns)
Index(['Land', 'Stadt', 'Land_german', 'lat', 'lon'], dtype='object')
In [144]:
df_all = df_all.rename(columns={'Zielland1_german': 'Land_german'}) # die Spalte mit Ländernamen soll in beiden Tabellen
#gleichen Namen tragen
df_all = df_all.rename(columns={'Zieljahr1': 'Ausreisejahr'})
df_all['Ausreisejahr'] = df_all['Ausreisejahr'].astype(int)
In [145]:
df_merged = pd.merge(df_koord, df_all, on='Land_german', how='right') # Zusammenfügung der Tabellen
df_merged = df_merged.dropna()
print(df_merged[:10])
Land Stadt Land_german lat lon Ausreisejahr \ 0 Belgium Brussels Belgien 50.846557 4.351697 1933 1 Brazil Brasilia Brasilien -10.333333 -53.200000 1933 2 China Beijing China 39.905714 116.391297 1933 3 Denmark Copenhagen Dänemark 55.686724 12.570072 1933 4 France Paris Frankreich 48.853495 2.348391 1933 5 Kyrgyzstan Bishkek Kirgisistan 42.877789 74.606693 1933 6 Latvia Riga Lettland 56.949398 24.105185 1933 7 Luxembourg Luxembourg Luxemburg 49.611277 6.129799 1933 8 Morocco Rabat Marokko 34.022360 -6.834022 1933 9 Netherlands Amsterdam Niederlande 52.373080 4.892453 1933 Häufigkeit 0 7 1 1 2 50 3 24 4 73 5 1 6 3 7 1 8 1 9 46
In [146]:
fig = px.scatter_geo(df_merged,
lat='lat',
lon='lon',
animation_frame="Ausreisejahr",
hover_data = {'Ausreisejahr': True, 'Land_german': True, 'lat': False, 'lon': False},
width=1100, height=650, size='Häufigkeit', color='Häufigkeit', opacity = 0.8, size_max=30,
projection='robinson', color_continuous_scale=px.colors.sequential.Bluered, title = "Zielländer und Ausreisejahre")
# Setzt die Colorbar-Skala aus
fig.update_coloraxes(showscale=False)
fig.update_traces(hovertemplate= # hover-Anweisungen
'<b>%{customdata[1]}</b><br>' +
'Jahr: %{customdata[0]}<br>' +
'Häufigkeit: %{marker.size}<br>'
)
for f in fig.frames: # Aktualisierung der Hover-Anweisungen für die Animation
f.data[0].update(hovertemplate='<b>%{customdata[1]}</b><br>Jahr: %{customdata[0]}<br>Häufigkeit: %{marker.size}')
# Optional: Anpassung der Markierung
fig.update_traces(marker_sizemin=4)
# Anzeige
fig.show()