import numpy as np
import pandas as pd
pd.options.plotting.backend = "plotly"
from gettsim import (
compute_taxes_and_transfers,
create_synthetic_data,
set_up_policy_environment,
)
Kinder & Bürgergeld#
In diesem Notebook beschäftigen wir uns damit, wie Kinder das Bürgergeld und die resultierenden Arbeitsanreize beeinflussen.
Von der Struktur her ist es fast dasselbe wie das Notebook in der letzten Präsenzphase. Wir erstellen 5 Typen von Haushalten:
1 Erwachsener
1 Erwachsener, 1 Kind
2 Erwachsene
2 Erwachsene, 1 Kind
2 Erwachsene, 2 Kinder
Zunächst beschränken wir uns auf die Transfers und Transferentzugsraten. Dieser Teil ist vorprogrammiert. Bitte gehen Sie wie üblich langsam durch und versuchen Sie, die einzelnen Schritte zu verstehen.
Anschließend bringen wir Transfers und Steuern zusammen und Sie berechnen selbständig die Gesamtbelastung.
Erstellung des Steuer- und Transfersystems und der Daten#
Wir setzen zunächst wieder die Parameter des Steuer- und Transfersystems auf die am Anfang des Jahres 2023 fest.
params_dict, policy_func_dict = set_up_policy_environment("2023-01-01")
Nun erstellen wir die benötigten Datensätze. Ab dem zweiten Datensatz passen wir auch die ID jeder Person und jedes Haushalts an, damit diese eindeutig sind.
min_einkommen = 0
max_einkommen = 10_000
anzahl_schritte = 1_001
# Ein Erwachsener, keine Kinder
df_1e = create_synthetic_data(
n_adults=1,
n_children=0,
specs_heterogeneous={
"bruttolohn_m": [
[i] for i in np.linspace(min_einkommen, max_einkommen, anzahl_schritte)
],
},
)
df_1e
# Ein Erwachsener, ein Kind
df_1e_1k = create_synthetic_data(
n_adults=1,
n_children=1,
specs_heterogeneous={
"bruttolohn_m": [
[i, 0] for i in np.linspace(min_einkommen, max_einkommen, anzahl_schritte)
],
},
)
# IDs anpassen
for var in ["hh_id", "tu_id", "p_id"]:
df_1e_1k[var] += 1 + df_1e[var].max()
df_1e_1k
# Zwei Erwachsene, keine Kinder
df_2e = create_synthetic_data(
n_adults=2,
n_children=0,
specs_heterogeneous={
"bruttolohn_m": [
[i / 2, i / 2]
for i in np.linspace(min_einkommen, max_einkommen, anzahl_schritte)
],
},
)
# IDs anpassen
for var in ["hh_id", "tu_id", "p_id"]:
df_2e[var] += 1 + df_1e_1k[var].max()
df_2e
# Zwei Erwachsene, ein Kind
df_2e_1k = create_synthetic_data(
n_adults=2,
n_children=1,
specs_heterogeneous={
"bruttolohn_m": [
[i / 2, i / 2, 0]
for i in np.linspace(min_einkommen, max_einkommen, anzahl_schritte)
],
},
)
# IDs anpassen
for var in ["hh_id", "tu_id", "p_id"]:
df_2e_1k[var] += 1 + df_2e[var].max()
df_2e_1k
# Zwei Erwachsene, zwei Kinder
df_2e_2k = create_synthetic_data(
n_adults=2,
n_children=2,
specs_heterogeneous={
"bruttolohn_m": [
[i / 2, i / 2, 0, 0]
for i in np.linspace(min_einkommen, max_einkommen, anzahl_schritte)
],
},
)
for var in ["hh_id", "tu_id", "p_id"]:
df_2e_2k[var] += 1 + df_2e_1k[var].max()
df_2e_2k
Nun erstellen wir einen großen Datensatz, der die eben erstellten enthält.
inputs_personen = pd.concat(
[df_1e, df_1e_1k, df_2e, df_2e_1k, df_2e_2k],
names=["Haushaltstyp"],
keys=[
"1 Erwachsener",
"1 Erwachsener, 1 Kind",
"2 Erwachsene",
"2 Erwachsene, 1 Kind",
"2 Erwachsene, 2 Kinder",
],
)
inputs_personen
Zusätzlich bestimmen wir das zu versteuernde Einkommen und setzen die Heiz- und Mietkosten.
inputs_personen["_zu_verst_eink_ohne_kinderfreib_tu"] = (
inputs_personen.groupby("tu_id")["bruttolohn_m"].transform("sum") * 12
)
inputs_personen["heizkosten_m_hh"] = 50.0
inputs_personen["bruttokaltmiete_m_hh"] = 350.0
inputs_personen
Nun können wir die Steuern und Transfers der Haushalte genau wie in den letzten Wochen
mittels GETTSIM bestimmen. Wir berechnen zusätzlich den Unterhaltsvorschuss
(unterhaltsvors_m
). Dies ist eine Transferzahlung, falls eine alleinerziehende Person
keine (oder zu geringe) Unterhaltszahlungen erhält. Wir nehmen in diesem Notebook an,
dass Kinder von Alleinerziehenden keine Unterhaltszahlungen erhalten und deshalb den
Unterhaltsvorschuss als Transfer erhalten.
Bei der Berechnung der Steuerlast vernachlässigen wir die gesetzlich vorgeschriebenen
Rundungen, indem wir rounding=False
als Argument in die Funktion aufnehmen. Dies sorgt
dafür, dass die später zu berechnenden Grenzbelastungen keine (kleinen) Sprünge durch
Rundungen aufweisen.
ergebnisse_personen = compute_taxes_and_transfers(
data=inputs_personen,
functions=policy_func_dict,
params=params_dict,
columns_overriding_functions=[
"_zu_verst_eink_ohne_kinderfreib_tu",
],
targets=[
"kindergeld_m_hh",
"eink_st_tu",
"soli_st_tu",
"sozialv_beitr_m",
"arbeitsl_geld_2_vor_vorrang_m_hh",
"unterhaltsvors_m",
],
rounding=False,
)
ergebnisse_personen.index.name = "p_id"
ergebnisse_personen
# Mithilfe der ID den Bruttolohn an Ergebnis anhängen
ergebnisse_personen = ergebnisse_personen.join(
inputs_personen.reset_index().set_index("p_id")[["hh_id", "bruttolohn_m"]],
)
Nun aggregieren wir die Steuer- und Transferzahlungen auf Haushaltsebene.
ergebnisse = ergebnisse_personen.groupby("hh_id").agg(
{
"bruttolohn_m": lambda x: x.sum(),
"kindergeld_m_hh": lambda x: x.max(),
"eink_st_tu": lambda x: x.max() / 12,
"soli_st_tu": lambda x: x.max() / 12,
"sozialv_beitr_m": lambda x: x.sum(),
"arbeitsl_geld_2_vor_vorrang_m_hh": lambda x: x.max(),
"unterhaltsvors_m": lambda x: x.sum(),
},
)
Da wir nun Variablen auf Haushaltsebene haben, benennen wir diese noch korrekt mittels .rename()
. Diese Methode ordnet einem alten Variablennahmen (bspw. bruttolohn_m
) einen neuen Namen zu (bspw. bruttolohn_hh_m
).
ergebnisse = ergebnisse.rename(
columns={
"bruttolohn_m": "bruttolohn_m_hh",
"sozialv_beitr_m": "sozialv_beitr_m_hh",
"unterhaltsvors_m": "unterhaltsvors_m_hh",
},
)
ergebnisse
Zuletzt fügen wir den Haushaltstyp unserem DataFrame mit den Ergebnissen hinzu und setzen den Index korrekt.
ergebnisse = ergebnisse.join(
inputs_personen.reset_index().set_index("hh_id")["Haushaltstyp"],
).drop_duplicates()
ergebnisse = ergebnisse.set_index(["Haushaltstyp", "bruttolohn_m_hh"])
ergebnisse
Transfers und Transferentzugsrate#
Nun errechnen wir die gesamten Transfers und die Entzugsraten.
ergebnisse["transfers"] = (
ergebnisse["kindergeld_m_hh"]
+ ergebnisse["arbeitsl_geld_2_vor_vorrang_m_hh"]
+ ergebnisse["unterhaltsvors_m_hh"]
)
ergebnisse["transferentzugsrate"] = (
ergebnisse["transfers"] - ergebnisse.groupby("Haushaltstyp")["transfers"].shift(-1)
) / 10
display(ergebnisse.head())
display(
ergebnisse.query("Haushaltstyp == '1 Erwachsener, 1 Kind'").head(),
)
display(ergebnisse.tail())
Wir untersuchen erstmal nur Haushalte mit bruttolohn_m_hh < 3000
.
ergebnisse_klein = ergebnisse.query("bruttolohn_m_hh < 3000")
ergebnisse_klein
Wir schauen uns zunächst die Transfers an.
ergebnisse_1e = ergebnisse_klein.query(
"Haushaltstyp == '1 Erwachsener' | Haushaltstyp == '1 Erwachsener, 1 Kind'",
)
ergebnisse_1e.reset_index().plot.line(
x="bruttolohn_m_hh",
y="transfers",
color="Haushaltstyp",
title="Transfers bei 1 Erwachsenen",
)
Hinweis: Die Zeichenketten (strings), die das Argument der folgenden
.query()
-Methode bilden, werden von Python automatisch aneinandergehängt. So können
wir die Abfrage lesbarer gestalten.
ergebnisse_2e = ergebnisse_klein.query(
"Haushaltstyp == '2 Erwachsene' | "
"Haushaltstyp == '2 Erwachsene, 1 Kind' | "
"Haushaltstyp == '2 Erwachsene, 2 Kinder'",
)
ergebnisse_2e.reset_index().plot.line(
x="bruttolohn_m_hh",
y="transfers",
color="Haushaltstyp",
title="Transfers bei 2 Erwachsenen",
)
Und nun die Transferentzugsraten.
Tipp zur besseren Übersicht: Sie können einzelne Haushaltstypen ausblenden indem Sie in der Legende des Plots diesen abwählen.
ergebnisse_1e.reset_index().plot.line(
x="bruttolohn_m_hh",
y="transferentzugsrate",
color="Haushaltstyp",
title="Transferentzugsrate",
)
ergebnisse_2e.reset_index().plot.line(
x="bruttolohn_m_hh",
y="transferentzugsrate",
color="Haushaltstyp",
title="Transferentzugsrate",
)
Aufgabe 1: Interpretation der Graphiken#
Erklären Sie die wichtigsten Sprünge in den Linien für die Transferentzugsraten!
Hinweis: Bei Alleinerziehenden gibt es Leistungen, die wir nicht im Kurs besprochen haben.
Hier Platz für Ihre Antwort
Aufgabe 2: Haushaltseinkommen und Grenzbelastung#
Wiederholen Sie die Analyse ab “Transfers und Transferentzugsrate” für das verfügbare Haushaltseinkommen und die gesamte Grenzbelastung aus Transferentzug und Steuern!
Nutzen Sie für die Berechnung des verfügbaren Einkommens wieder das DataFrame ergebnisse
und nicht ergebnisse_klein
. Plotten Sie dann aber das DataFrame ergebnisse_klein
, welches in der mittleren Zelle erstellt wird.
ergebnisse_klein = ergebnisse.query("bruttolohn_m_hh < 3000")
Aufgabe 3: Interpretation der Unterschiede#
Was treibt die Unterschiede zwischen Haushalten mit Kindern und ohne Kinder? Verursachen diese Unterschiede unterschiedliche Arbeitsanreize?
Hier Platz für Ihre Antwort
Aufgabe 4#
Sehen Sie sich im folgenden die Bürgergeld-Transfers für Familien mit 2 Erwachsenen und 2 Erwachsenen mit einem Kind an. Die Kinder in unserem Datensatz sind 8 Jahre alt.
Warum entspricht der Unterschied zwischen dem Bürgergeldanspruch einer Familie mit und ohne Kind nicht genau dem Regelsatz eines 8-jährigen Kindes?
display(
ergebnisse.query("Haushaltstyp == '2 Erwachsene'").head(),
)
display(
ergebnisse.query("Haushaltstyp == '2 Erwachsene, 1 Kind'").head(),
)