Datenbericht

1 Datenbericht

Der Datenbericht dokumentiert alle im Projekt verwendeten Daten, von der Rohdatenbeschaffung bis hin zu den drei abgeleiteten Analyse-Datensätzen. Ziel ist die Nachvollziehbarkeit der Befunde und die Möglichkeit, den vollen Datenfluss von Dritten reproduzieren zu lassen.

1.1 Rohdaten

1.1.1 Übersicht der Rohdatensätze

Wir beziehen die Daten vom öffentlichen Export der OpenParlData-Plattform [1]. Die Plattform bietet eine API, wir nutzen jedoch direkt die Quelldateien unter files.openparldata.ch/exports/, die wöchentlich als gzippte NDJSON-Dateien aktualisiert werden. Für unsere Fragestellung (Alter, Eintritt und Amtsdauer von Bundespolitiker:innen) reichen zwei der rund 15 verfügbaren Exports.

Table 1: Übersicht der verwendeten Rohdatensätze.
Name Quelle Speicherort
persons.ndjson OpenParlData Export: Personeneinträge inkl. Biografie, Partei, Wahlkreis. data/raw/persons.ndjson (entpackt), bezogen von https://files.openparldata.ch/exports/persons.ndjson.gz
memberships.ndjson OpenParlData Export: Mitgliedschaften in Gremien (Räte, Kommissionen, Fraktionen, Parteien). data/raw/memberships.ndjson (entpackt), bezogen von https://files.openparldata.ch/exports/memberships.ndjson.gz

Das Beschaffungs-Skript eda/1_gather_data.py lädt beide Dateien herunter, entpackt sie und konvertiert sie nach Parquet. Bereits vorhandene Dateien werden nicht erneut heruntergeladen.

# eda/1_gather_data.py (Auszug)
OPENPARL_BASE = "https://files.openparldata.ch/exports"
FILES = ["persons", "memberships"]

def ensure_ndjson(name: str) -> Path:
    ndjson_path = RAW_DIR / f"{name}.ndjson"
    gz_path = RAW_DIR / f"{name}.ndjson.gz"
    if ndjson_path.exists():
        return ndjson_path
    if not gz_path.exists():
        urllib.request.urlretrieve(f"{OPENPARL_BASE}/{name}.ndjson.gz", gz_path)
    with gzip.open(gz_path, "rb") as f_in, open(ndjson_path, "wb") as f_out:
        shutil.copyfileobj(f_in, f_out)
    return ndjson_path

Rechtliches und Governance. OpenParlData ist eine öffentliche Initiative ohne formelle Lizenzangabe; die zugrundeliegenden Daten stammen aus den offiziellen Biografien der parlament.ch Webseite und sind als öffentlich zugängliche Verwaltungsdaten zu verstehen. Die Daten sind somit als “öffentlich” einzuordnen.

1.1.2 Details persons.ndjson

Der Personen-Export enthält biografische Stammdaten zu allen je erfassten Mandatsträger:innen auf Bundes- und Kantonsebene: Name, Geburtsdatum, Geschlecht, Partei, Wahlkreis, parlamentarischer Sektor (Nationalrat oder Ständerat), aktuelle Aktivität sowie eine Vielzahl von Querverweisen auf externe IDs (Wikidata, parlament.ch). Wir filtern für unsere Analyse auf body_key == "CHE", also auf die Bundesebene.

1.1.2.1 Datenkatalog

Der vollständige Katalog mit allen 60 Spalten liegt unter eda/output/catalogue_persons_clean_CHE.csv. Hier sind die für die Altersanalyse relevanten Spalten:

Table 2: Datenkatalog persons.ndjson (Auszug der projektrelevanten Spalten).
Index Spalte Datentyp Fehlend (%) Unique
0 1 id int64 0.0 3916
1 2 body_key object 0.0 1
2 3 fullname object 0.0 3868
3 4 firstname object 0.0 1441
4 5 lastname object 0.0 2470
5 6 birthday datetime64[ms] 6.7 3542
6 7 gender object 6.6 2
7 8 party_de object 7.4 77
8 9 party_harmonized_de object 18.5 21
9 10 electoral_district_de object 7.0 74
10 11 parliament_sector object 93.7 2
11 12 active object 0.4 2

1.1.2.2 Datencharakteristik und Qualität

Die zentrale Variable für unsere Analyse ist birthday. Auf Bundesebene ist die Abdeckung exzellent:

CHE-Personen total: 3,916
Davon mit Geburtsdatum: 3,655 (93.3 %)
Im plausiblen Bereich (1800–2015): 3,576
Frühester Geburtstag: 1800-01-18
Spätester Geburtstag: 1996-12-26
Figure 1: Anzahl CHE-Personen mit erfasstem Geburtsdatum je Geburtsjahrzent. Die Abdeckung ist über alle Jahrzente hoch.

Die Geschlechtsangabe ist ebenfalls flächendeckend erfasst:

Geschlecht Anzahl Anteil (%)
0 m 3352 85.6
1 f 307 7.8
2 (fehlend) 257 6.6

Bei der Parteizugehörigkeit fällt auf, dass viele Parteinamen über die Zeit gewandert sind (CVP, Mitte, FDP-Liberale usw.). OpenParlData stellt unter party_harmonized_de bereits konsolidierte Bezeichnungen bereit; wir nutzen sie für historische Vergleiche.

Table 3: Häufigste harmonisierte Parteibezeichnungen (Top 10).
Anzahl
party_harmonized_de
FDP.Die Liberalen 1211
Christlichdemokratische Volkspartei der Schweiz 732
None 723
Sozialdemokratische Partei 493
Schweizerische Volkspartei 335
Liberal-Demokratische Partei 108
Die Grünen 65
Landesring der Unabhängigen 62
Die Mitte 53
Grünliberale Partei 26

1.1.3 Details memberships.ndjson

Der Mitgliedschafts-Export enthält pro Person eine Zeile pro Gremium, in dem die Person sass oder noch sitzt: Nationalrat, Ständerat, Kommissionen, Fraktionen, Interessengruppen, Parteien. Jede Mitgliedschaft hat ein Anfangs- und Enddatum (begin_date, end_date), einen Typ (type_harmonized_de) und einen Gruppennamen (group_name_de). Diese Doppelung erlaubt es uns, die Parlamentssitze (Typ Parlament (Legislativrat) mit Gruppe Nationalrat oder Ständerat) sauber zu isolieren.

1.1.3.1 Datenkatalog

Vollständiger Katalog: eda/output/catalogue_memberships_clean_CHE.csv. Relevant für unsere Analyse:

Table 4: Datenkatalog memberships.ndjson (Auszug der projektrelevanten Spalten).
Index Spalte Datentyp Fehlend (%) Unique
0 1 id int64 0.0 22122
1 2 body_key object 0.0 1
2 3 person_id float64 0.0 3708
3 4 group_name_de object 0.0 445
4 5 role_name_de object 27.1 15
5 6 begin_date datetime64[ms] 24.3 1544
6 7 end_date datetime64[ms] 29.9 2044
7 8 active object 2.0 2
8 9 type_harmonized_de object 0.0 9

1.1.3.2 Datencharakteristik und Qualität

Auf Bundesebene existieren rund 22’000 Mitgliedschaftseinträge. Die Mehrheit entfällt auf Kommissionen und Interessengruppen; für unsere Frage interessieren ausschliesslich die Mitgliedschaften vom Typ Parlament (Legislativrat):

Figure 2: Verteilung der CHE-Mitgliedschaften nach Typ. Für die Altersanalyse verwenden wir ausschliesslich den Typ ‘Parlament (Legislativrat)’.

Innerhalb des Typs Parlament (Legislativrat) ergibt sich eine klare Zweiteilung in Nationalrat und Ständerat:

Table 5: Aufteilung der Parlamentsmitgliedschaften auf die beiden Kammern.
Anzahl
group_name_de
Nationalrat 4398
Ständerat 1219

Das Beobachtungsfenster reicht bis 1848 zurück:

Frühestes begin_date: 1848-11-06
Spätestes begin_date: 2026-06-01
Anteil ohne end_date (laufende Mandate): 4.4 %

1.2 Verarbeitete Daten

Aus den beiden Rohdatensätzen erzeugt eda/2_etl_politicians.py drei kompakte Analyse-Tabellen. Die Verarbeitungsschritte sind:

  1. Bundesebene isolieren (body_key == "CHE").
  2. Geburtstage validieren (Geburtsjahr zwischen 1800 und 2015).
  3. Parlamentssitze isolieren (type_harmonized_de == "Parlament (Legislativrat)" und Gruppe Nationalrat oder Ständerat).
  4. Join Mitgliedschaften × Personen via person_id.
  5. Anreichern pro Mitgliedschaft mit entry_age, exit_age, duration_years.
# eda/2_etl_politicians.py (Auszug)
parl["entry_age"] = ((parl["begin_date"] - parl["birthday"]).dt.days / 365.25).round(2)
parl["exit_age"]  = ((parl["end_date_eff"] - parl["birthday"]).dt.days / 365.25).round(2)
parl["duration_years"] = ((parl["end_date_eff"] - parl["begin_date"]).dt.days / 365.25).round(2)

Für laufende Mandate (kein end_date) verwenden wir das heutige Datum als provisorisches Ende; die betroffenen Zeilen werden über is_active = True markiert, sodass nachgelagerte Auswertungen sie bei Bedarf ausschliessen können.

1.2.1 Übersicht der verarbeiteten Datensätze

Table 6: Übersicht der drei verarbeiteten Datensätze.
Name Beschreibung Speicherort
politicians.parquet Eine Zeile pro Bundespolitiker:in mit aggregierten Karriere-Kennzahlen. data/processed/politicians.parquet
parliament_memberships.parquet Eine Zeile pro NR- oder SR-Mitgliedschaft mit Alters- und Dauer-Berechnungen. data/processed/parliament_memberships.parquet
parliament_yearly.parquet Jahres-Snapshot per 1. Juli: wer war im Parlament, wie alt? data/processed/parliament_yearly.parquet

1.2.2 Details politicians.parquet

Eine Zeile pro Person, die mindestens einmal in Nationalrat oder Ständerat sass und ein erfasstes Geburtsdatum hat.

Table 7: Datenkatalog politicians.parquet.
Index Spalte Datentyp Fehlend (%) Unique
0 1 person_id float64 0.0 3546
1 2 firstname object 0.0 1307
2 3 lastname object 0.0 2256
3 4 birthday datetime64[ms] 0.0 3437
4 5 gender object 0.0 2
5 6 party_de object 0.5 77
6 7 party_harmonized_de object 11.8 21
7 8 canton object 0.0 74
8 9 first_entry_date datetime64[ms] 0.0 680
9 10 last_seat_end datetime64[ms] 0.0 1146
10 11 entry_age float64 0.0 2156
11 12 total_tenure_years float64 0.0 1365
12 13 num_memberships int64 0.0 9
13 14 chambers object 0.0 3
14 15 currently_active bool 0.0 2
15 16 age_today float64 0.0 1572
Anzahl Bundespolitiker:innen in der Analyse: 3,546
Davon aktuell im Amt: 237

Univariate Statistiken (Jahre):
entry_age total_tenure_years age_today
count 3546.0 3546.0 3546.0
mean 46.3 10.7 134.7
std 8.7 7.8 51.6
min 21.3 -0.0 29.4
10% 34.9 2.4 67.4
50% 46.3 9.0 133.7
90% 57.7 21.0 207.2
max 81.4 48.5 226.3
Figure 3: Verteilung des Eintrittsalters über alle 3’546 Bundespolitiker:innen (1850–2025).
Figure 4: Eintrittsalter gegen Gesamt-Mandatsdauer. Wer früh einsteigt, kann länger bleiben; die schwache negative Korrelation ist sichtbar.

1.2.3 Details parliament_memberships.parquet

Eine Zeile pro einzelne Mitgliedschaft im Nationalrat oder Ständerat.

Table 8: Datenkatalog parliament_memberships.parquet.
Index Spalte Datentyp Fehlend (%) Unique
0 1 person_id float64 0.0 3546
1 2 firstname object 0.0 1307
2 3 lastname object 0.0 2256
3 4 birthday datetime64[ms] 0.0 3437
4 5 gender object 0.0 2
5 6 party_de object 0.4 77
6 7 party_harmonized_de object 10.1 21
7 8 electoral_district_de object 0.0 74
8 9 chamber object 0.0 2
9 10 begin_date datetime64[ms] 0.0 757
10 11 end_date datetime64[ms] 4.4 1279
11 12 end_date_eff datetime64[ms] 0.0 1280
12 13 entry_age float64 0.0 2776
13 14 exit_age float64 0.0 2892
14 15 duration_years float64 0.0 1140
15 16 is_active bool 0.0 2
Figure 5: Verteilung der Mandatsdauer pro Kammer, nur abgeschlossene Mandate. Der Ständerat zeigt längere Mandate (Median sechs Jahre versus vier im Nationalrat) bei stärkerer Streuung.

1.2.4 Details parliament_yearly.parquet

Jahres-Snapshot: für jedes Jahr von 1850 bis 2025 eine Zeile pro Person, die am 1. Juli dieses Jahres in NR oder SR sass, plus ihr Alter zu jenem Stichtag. Dieser Datensatz ist Kernstück der Haupt-Visualisierung.

Table 9: Datenkatalog parliament_yearly.parquet.
Index Spalte Datentyp Fehlend (%) Unique
0 1 person_id float64 0.0 3478
1 2 firstname object 0.0 1274
2 3 lastname object 0.0 2224
3 4 chamber object 0.0 2
4 5 gender object 0.0 2
5 6 party_de object 0.5 76
6 7 party_harmonized_de object 9.8 21
7 8 age float64 0.0 4559
8 9 year int64 0.0 176
Figure 6: Anzahl Parlamentsmitglieder pro Jahr und Kammer. Der Nationalrat wuchs in mehreren Etappen auf die heutigen 200 Sitze; der Ständerat hält bei 46.
Figure 7: Median-Alter pro Kammer über die Zeit. Das ist die Headline-Grafik der Analyse und beantwortet die Forschungsfrage direkt.

1.3 Schlüsselbefunde

Befund Quelle
Median-Alter NR in den 2020ern: 51.6 Jahre, so jung wie seit 100 Jahren nicht mehr. parliament_yearly Median pro Jahrzent
Median-Alter SR liegt aktuell bei rund 60 Jahren und ist konstant höher als NR. parliament_yearly Median pro Jahrzent
Höhepunkt der Alterung war nicht heute, sondern in den 1950ern (NR 56, SR 61). parliament_yearly Median pro Jahrzent
Eintrittsalter ist seit 1880 stabil bei 46 bis 49 Jahren. politicians.entry_age Median pro Eintrittsjahrzent

1.4 Datenqualität und Limitierungen

  • Geburtstagslücke: Rund 7 % der Bundespolitiker:innen haben kein erfasstes Geburtsdatum. Die Lücke konzentriert sich auf historische Datensätze. Für moderne Mandate ist die Abdeckung praktisch vollständig.
  • Aktive Mandate: Für laufende Mandate ist end_date leer; für Berechnungen wird das heutige Datum als provisorisches Ende verwendet.
  • Parteibezeichnungen: Parteinamen ändern sich (CVP zu Die Mitte, FDP zu FDP-Liberale). Wir nutzen die harmonisierten Bezeichnungen party_harmonized_de.
  • Stichtag des Snapshots: Wir messen die Altersverteilung jeweils am 1. Juli. Mandate, die zwischen Januar und Juli beginnen oder enden, sind in dem jeweiligen Jahr je nach Datum enthalten oder nicht.

1.5 Reproduzierbarkeit

uv sync
uv run python eda/1_gather_data.py     # Download + NDJSON zu Parquet
uv run python eda/2_etl_politicians.py # ETL für die Altersanalyse
uv run python eda/3_eda.py             # EDA-Dump in eda/output/
uv run streamlit run deployment/app.py # Interaktives Visualisierungsprodukt

Die vollständigen EDA-Outputs befinden sich im Ordner eda/output/.

1.6 Quellen

[1]
OpenParlData, “OpenParlData: Offene daten zum schweizer parlament.” Accessed: May 17, 2026. [Online]. Available: https://openparldata.ch