Präsenzphase: Einkommensteuer#

In der Selbstlernphase haben Sie bereits für bestimme Einkommen die Steuerlast, den Durchschnitts- und den Grenzsteuersatz bestimmt. Auf diesem Wissen werden wir jetzt aufbauen und die Grundlagen für die Analyse von Reformen legen.

import numpy as np
import pandas as pd

pd.options.plotting.backend = "plotly"

Aufgabe 1: Pentabilities — Umgang mit Emotionen und Denkvermögen (10min)#

Bitte diskutieren Sie in Ihrer Gruppe die folgenden Fragen. Wie in den letzten Wochen gibt es weder richtige oder falsche Antworten, noch müssen Sie sich auf eine Antwort einigen. Es geht darum, dass Sie sich mit dem Konzept vertraut machen und dieses diskutieren. Diese Woche beschäftigen wir uns mit den Dimensionen Umgang mit Emotionen und Denkvermögen. Um sich besser damit vertraut zu machen was Pentabilities mit diesen Dimensionen assoziiert, diskutieren Sie bitte in Ihrer Gruppe was die einzelnen Verhaltensweisen bedeuten. Anschließend wählen Sie die zwei aus, welche für Sie am relevantesten sind.

Umgang mit Emotionen

  • Verbreitet gute Laune

  • Bleibt unter Druck ruhig

  • Kontrolliert Emotionen, wenn Konflikte aufkommen

  • Akzeptiert, dass Fehler gemacht werden könnten

  • Akzeptiert, dass eigene Ansätze fehlschlagen

  • Passt Verhalten den Umständen an

Denkvermögen

  • Wendet vorhandenes Wissen auf neue Inhalte an

  • Reflektiert gut den Inhalt

  • Reflektiert gut interne zwischenmenschliche Abläufe

  • Stelle sinnvolle Fragen (um Verständnis zu verbesern oder weiterzukommen)

  • Hat kreative Ideen (testet alternative Wege aus)

  • Schlägt gute Strategien zur Problemlösung vor

  • Plant und priorisiert Aufgaben

  • Wille, andere Perspektiven kennenzulernen

  • Drückt Ideen effizient aus (Korrektur, Präzision, Struktur)

Bitte schauen Sie auch unter den einzelnen Beschreibungen nach, um sich genauer damit auseinanderzusetzen, was hinter den Begriffen steht.

Aufgabe 2: Graphische Darstellung des Einkommensteuertarifs (gesamt 60min)#

Folgende Funktion errechnet für das Jahr 2023 die Einkommensteuerlast abhängig vom zu versteuernden Einkommen:

def einkommensteuer_2023(zu_versteuerndes_einkommen):
    """Berechne Einkommensteuer 2023.

    Args:
        zu_versteuerndes_einkommen (float): Zu versteuerndes Einkommen

    Output:
        Steuerlast(float): Steuerlast 2023
    """
    x = np.floor(zu_versteuerndes_einkommen)
    y = (x - 10_908) / 10_000
    z = (x - 15_999) / 10_000

    if x <= 10_908:
        return 0
    elif x <= 15_999:
        return np.floor((979.18 * y + 1_400) * y)
    elif x <= 62_809:
        return np.floor((192.59 * z + 2_397) * z + 966.53)
    elif x <= 277_825:
        return np.floor(0.42 * x - 9_972.98)
    else:
        return np.floor(0.45 * x - 18_307.73)

Aufgabe 2.1: Verständnis der Funktion (8min)#

Schauen Sie sich die Funktion einkommensteuer_2023 etwas genauer an und kontrollieren Sie, dass die Funktion korrekt den Gesetzestext implementiert.

Was macht die Funktion np.floor? Und warum ist sie notwendig für die korrekte Implementierung der Einkommensteuer?

Aufgabe 2.2: Erste Anwendung der Funktion (2min)#

In der Selbstlernphase haben Sie die Steuerlast bei einem zu versteuerndem Einkommen von 60.000€ ausgerechnet. Nutzen Sie die Funktion um das Ergebnis zu replizieren.

Aufgabe 2.3: Berechnung des Durchschnittssteuersatzes (7min)#

Wie hoch ist dementsprechend der Durchschnittssteuersatz bei einem zu versteuerndem Einkommen von 60.000€?

Schreiben Sie Code, mit dem Sie den Durchschnittssteuersatz ausrechnen können. Der Code soll keine explizit ausgeschriebene Zahl beinhalten. Er soll also ausschließlich die Variable zu_versteuerndes_einkommen und die Funktion einkommensteuer_2023 aufrufen.

Aufgabe 2.4: Steuerlast 2020 (15min)#

Ziel dieser Aufgabe ist, dass Sie selbstständig eine Funktion abändern.

Auf der Website vom Steuerrechner, den sie bereits aus der Selbstlernphase kennen, finden Sie auch die Einkommensteuerformel für das Jahr 2020. Wählen Sie dafür das Jahr 2020 als Berechnungsjahr und drücken Sie auf “berechnen”.

Kopieren Sie den Code von oben, der die Funktion einkommensteuer_2023 implementiert. Nennen Sie die neue Funktion entsprechend “einkommensteuer_2020”. Dann passen Sie die Werte der Funktion an, sodass Sie die Einkommensteuer für das Jahr 2020 berechnen:

Wie hoch war im Jahr 2020 die Steuerlast bei einem zu versteuerndem Einkommen von 60.000€? Gleichen Sie ihr Ergebnis mit dem Steuerrechner ab.

Um dem Unterschied in der realen Steuerlast zwischen 2020 und 2023 näher zu kommen, müssen wir die Inflation berücksichtigen. Deshalb inflationieren Sie bitte die 60.000€ unter Berücksichtigung der Inflationsraten von 2021 bis 2023 (prognostiziert). (Runden Sie auf Tausend Euro)

Dann berechnen Sie für das berechnete real-äquivalente Einkommen die Steuerlast in 2023.

Vergleichen Sie diese neue Steuerlast in 2023 mit der inflationierten Steuerlast von 2020.

Aufgabe 2.5: Plot der absoluten Steuerlast in Abhängigkeit vom Einkommen (15min)#

Wir werden Ihnen zunächst zeigen, wie Sie die absolute Steuerlast für das Jahr 2023 plotten können. Anschließend werden Sie Code schreiben, mit dem Sie die Wirkung der Steuerreform zu Jahresbeginn 2023 darstellen können.

Zunächst definieren wir max_einkommen und schrittgröße. Die Namen sind vermutlich selbsterklärend, vollziehen Sie aber sicherheitshalber am dataFrame die Bedeutung nach, indem sie die Variablenwerte verändern.

max_einkommen = 100_001
schrittgröße = 1_000
data = {}
data = pd.DataFrame(columns=("einkommen", "steuerlast_2023", "steuerlast_2020"))
data["einkommen"] = range(1000, max_einkommen, schrittgröße)
data

Die Steuerlast berechnen wir, indem wir die oben definierte Funktion einkommensteuer_2023 auf jede Zelle anwenden. Stimmt der Eintrag für ein Einkommen von 60.000€?

data["steuerlast_2023"] = data["einkommen"].apply(lambda x: einkommensteuer_2023(x))
data

Passen sie den Code an, um auch die Spalte steuerlast_2020 mit Daten zu füllen.

Die Steuerlast für das Jahr 2023 können Sie einfach plotten:

data.plot(
    x="einkommen",
    y="steuerlast_2023",
    labels={
        "einkommen": "Zu versteuerndes Einkommen",
        "steuerlast_2023": "Absolute Steuerlast 2023",
    },
)

Berechnen Sie nun die absolute Differenz in der Steuerlast zwischen 2020 und 2023 in Abhängigkeit vom Einkommen. Mathematisch ausgedrückt sind Sie interessiert an

einkommensteuer_2023(einkommen) - einkommensteuer_2020(einkommen)

für jeden der oben angegebenen Einkommensschritte.

Und plotten Sie ihr Ergebnis:

Aufgabe 2.6: Durchschnittssteuersatz (10min)#

Berechnen Sie den Durchschnittssteuersatz im Jahr 2023 in Abhängigkeit vom Einkommen.

data["durchschnittssteuersatz_2023"] = data["steuerlast_2023"] / data["einkommen"]
data

Plotten Sie den Durchschnittssteuersatz.

Wie hoch ist in etwa der Durchschnittssteuersatz bei einem Einkommen von 60.000€?

Aufgabe 2.7: Plotten des Grenzsteuersatzes (3min)#

Für die Berechnung des Grenzsteuersatzes mit der Formel $\frac{f(x + h) - f(x)}{h}$ mit “kleinem” $h$ können Sie die oben definierte Funktion einkommensteuer_2023 nicht verwenden.

Warum nicht?

Deshalb erhalten Sie hier die angepasste Funktion für das Jahr 2023.

def einkommensteuer_2023_ohne_rundung(zu_versteuerndes_einkommen):
    """Berechne Einkommensteuer 2023.

    Args:
        zu_versteuerndes_einkommen (float): Zu versteuerndes Einkommen

    Output:
        Steuerlast(float): Steuerlast 2023
    """
    x = zu_versteuerndes_einkommen
    y = (x - 10_908) / 10_000
    z = (x - 15_999) / 10_000

    if x <= 10_908:
        return 0
    elif x <= 15_999:
        return (979.18 * y + 1_400) * y
    elif x <= 62_809:
        return (192.59 * z + 2_397) * z + 966.53
    elif x <= 277_825:
        return 0.42 * x - 9_972.98
    else:
        return 0.45 * x - 18_307.73

Wie Sie schon in der Selbstlernphase gesehen haben, gibt es zwei Möglichkeiten den Grenzsteuersatz auszurechnen: Sie können die Funktion ableiten oder das Problem numerisch lösen. Wir wählen hier die zweite Variante.

schrittgröße = 0.1

data["grenzsteuersatz_2023"] = data["einkommen"].apply(
    lambda x: (
        (
            einkommensteuer_2023_ohne_rundung(x + schrittgröße)
            - einkommensteuer_2023_ohne_rundung(x)
        )
        / schrittgröße
    ),
)

data.head()

Die folgende Zelle plottet den Grenzsteuersatz für das Jahr 2023:

data.plot.line(
    x="einkommen",
    y="grenzsteuersatz_2023",
    labels={
        "einkommen": "Zu versteuerndes Einkommen",
        "grenzsteuersatz_2023": "Grenzsteuersatz 2023",
    },
)

Wie hoch ist in etwa der Grenzsteuersatz bei einem Einkommen von 60.000€?

Aufgabe 3: Eigene Steuerreformen (gesamt 55min)#

Nun wollen wir Ihnen die Möglichkeit geben, ihre eigenen steuerpolitischen Präferenzen auszudrücken. Sehen Sie sich noch einmal die deutsche Einkommensteuerformel an und stellen Sie sich vor, sie würden die Grenzsteuersätze der Mittelschicht senken wollen. Das ist durch die komplexe Formel keine triviale Aufgabe!

Deshalb vereinfachen wir uns das Leben und schauen uns das Steuersystem von Österreich an. Denn Deutschland mit seiner komplizierten Formel im Gesetzestext ist eine sehr große Ausnahme, in allen (!) anderen OECD-Staaten setzt sich die Einkommensteuer stückweise linear zusammen. Das bedeutet, dass in diesen Systemen innerhalb einer Tarifzone die marginale Steuer konstant ist. Am leichtesten lässt sich das graphisch veranschaulichen, deshalb bauen wir wieder unsere Funktion zusammen.

Einleitung (5min)#

Wir definieren gleich eine Funktion, die das österreichische Steuersystem abbildet. Bitte ignorieren Sie den Inhalt der Funktion (wie sie aufgebaut ist, müssen Sie nicht verstehen und Sie werden wahrscheinlich viel Zeit verlieren, wenn Sie es versuchten).

Wichtig sind allein die Schwellenwerte von Intervallen und Grenzsteuersätze in diesen Intervallen, deren 2023er-Werte wir in der folgenden Zelle speichern (hier können Sie diese bei Interesse nachlesen):

tax_ö = {
    "steuerlast0": 0,
    "schwellenwert0": 0,
    "schwellenwerte": np.array(
        [11_693, 19_134, 32_075, 62_080, 93_120, 1_000_000, np.inf],
    ),
    "marginale steuer": np.array([0, 0.2, 0.3, 0.41, 0.48, 0.5, 0.55]),
}

Zudem benötigen wir aus technischen Gründen noch zwei weitere Inputs, ignorieren Sie diese einfach.

Die folgende Funktion nimmt die eben gespeicherten Werte und einen Wert für das Einkommen als Input und gibt die Steuerlast zurück.

def einkommensteuer_österreich(
    einkommen,
    steuerlast_min,
    schwellenwert_min,
    schwellenwerte,
    grenzsteuerlast,
):
    """Berechne Einkommensteuer 2023 in Österreich.

    Args:
        einkommen (float): Zu versteuerndes Einkommen
        steuerlast_min (float): steuerlast bei schwellenwert_min
            (nutze 0 für den ersten Aufruf)
        schwellenwert_min (float): Unterster Schwellenwert
            (nutze 0 für den ersten Aufruf)
        schwellenwerte (array): Schwellenwerte
        grenzsteuerlast (array): Marginale Steuern

    Output:
        steuerlast(float): steuerlast 2023 Östereich
    """
    if einkommen < schwellenwerte[0]:
        steuerlast = steuerlast_min + grenzsteuerlast[0] * (
            einkommen - schwellenwert_min
        )
    else:
        steuerlast_dieser_abschnitt = (
            schwellenwerte[0] - schwellenwert_min
        ) * grenzsteuerlast[0] + steuerlast_min
        next_schwellenwert_min = schwellenwerte[0]
        if len(schwellenwerte) > 1:
            steuerlast = einkommensteuer_österreich(
                einkommen,
                steuerlast_dieser_abschnitt,
                next_schwellenwert_min,
                schwellenwerte[1:],
                grenzsteuerlast[1:],
            )
        else:
            steuerlast = steuerlast_dieser_abschnitt + grenzsteuerlast[0] * (
                einkommen - schwellenwerte[0]
            )
    return steuerlast

Die absolute Steuerlast berechnet sich dann wie folgt:

einkommen = 60_000

einkommensteuer_österreich(
    einkommen=einkommen,
    steuerlast_min=tax_ö["steuerlast0"],
    schwellenwert_min=tax_ö["schwellenwert0"],
    schwellenwerte=tax_ö["schwellenwerte"],
    grenzsteuerlast=tax_ö["marginale steuer"],
)

Aufgabe 3.1: Erste Anwendung der Funktion (5min)#

Kontrollieren Sie für einige Einkommen die Korrektheit der Ergebnisse mit dem Brutto-Netto-Rechner für Österreich. Die Illustration der Rechenschritte auf der Homepage unten hilft Ihnen unter Umständen bei den nächsten Aufgaben.

Aufgabe 3.2: Plot des Durchschnittssteuersatzes (10min)#

Die folgende Zelle berechnet einen DataFrame mit der Steuerlast in Abhängigkeit vom Einkommen.

max_einkommen = 100_001
schrittgröße = 1_000
data_ö = {}
data_ö = pd.DataFrame(columns=("einkommen", "steuerlast"))
data_ö["einkommen"] = range(1000, max_einkommen, schrittgröße)

data_ö["steuerlast"] = data_ö["einkommen"].apply(
    lambda x: einkommensteuer_österreich(
        einkommen=x,
        steuerlast_min=tax_ö["steuerlast0"],
        schwellenwert_min=tax_ö["schwellenwert0"],
        schwellenwerte=tax_ö["schwellenwerte"],
        grenzsteuerlast=tax_ö["marginale steuer"],
    ),
)
data_ö.tail()

Berechnen Sie den Durchschnittssteuersatz, speichern Sie ihn in einer neuen Spalte von data_ö und plotten Sie ihn gegen das Einkommen.

Aufgabe 3.3: Plot des Grenzsteuersatzes (5min)#

Hier ist der Code für die Berechung des Grenzsteuersatzes:

schrittgröße = 1

data_ö["grenzsteuersatz"] = data_ö["einkommen"].apply(
    lambda x: (
        (
            einkommensteuer_österreich(
                einkommen=x + schrittgröße,
                steuerlast_min=tax_ö["steuerlast0"],
                schwellenwert_min=tax_ö["schwellenwert0"],
                schwellenwerte=tax_ö["schwellenwerte"],
                grenzsteuerlast=tax_ö["marginale steuer"],
            )
        )
        - einkommensteuer_österreich(
            einkommen=x,
            steuerlast_min=tax_ö["steuerlast0"],
            schwellenwert_min=tax_ö["schwellenwert0"],
            schwellenwerte=tax_ö["schwellenwerte"],
            grenzsteuerlast=tax_ö["marginale steuer"],
        )
        / schrittgröße
    ),
)
data_ö

Plotten Sie den Grenzsteuersatz. Was ist der Unterschied zum deutschen Grenzsteuersatz?

Aufgabe 3.4: Berechnung des Steueraufkommens (20min)#

Stellen Sie sich nun vor, dass in Österreich 210 repräsentative Menschen leben. Von diesen verdienen 20 Menschen 0€, 19 Menschen 5.000€, 18 Menschen 10.000€, 17 Menschen 15.000€, …, und 1 Mensch 95.000€. Wir erstellen dafür einen neuen DataFrame eink_vert_ö

max_einkommen = 95_001
schrittgröße = 5_000
eink_vert_ö = pd.DataFrame(
    columns=("einkommen", "anzahl menschen", "steuerlast_österreich"),
)

eink_vert_ö["einkommen"] = range(0, max_einkommen, schrittgröße)

eink_vert_ö["anzahl menschen"] = range(20, 0, -1)
eink_vert_ö

Berechnen Sie nun das Steueraufkommen. Nutzen Sie hierfür die Funktionen dot(), mit der sie Matrizen multiplzieren können.

Schritt 1: Berechnung der festgesetzten Einkommensteuer für jedes Einkommen in eink_vert_ö[“einkommen”]

eink_vert_ö["steuerlast_österreich"] = eink_vert_ö["einkommen"].apply(
    lambda x: einkommensteuer_österreich(
        x,
        tax_ö["steuerlast0"],
        tax_ö["schwellenwert0"],
        tax_ö["schwellenwerte"],
        tax_ö["marginale steuer"],
    ),
)
eink_vert_ö

Schritt 2: Berechnung des Steueraufkommens

Aufgabe 3.5: Anpassung an die eigenen Präferenzen (10min)#

Sie haben freie Hand über das österreichische Steuersystem bekommen und dürfen alles ändern, wie sie wollen!

Mit nur einer kleiner Nebenbedingung: Das Steueraufkommen sollte sich nicht wesentlich ändern.

Ändern Sie die Tarifgrenzen und marginalen Steuersätze, bis Sie mit dem Ergebnis zufrieden sind.

Hinweise:

  • steuerlast0 und schwellenwerte0 belassen Sie bitte einfach bei Null.

  • Die np.arrays für schwellenwerte und marginale steuer müssen jeweils dieselbe Länge haben, ansonsten können Sie diese mit Werten $\geq 0$ anpassen, wie Sie mögen

Rechnen Sie im Anschluss das gesamte Steueraufkommen und Plotten Sie den Grenz- und Durchschnittssteuersatz.

tax_eigenkreation = {
    "steuerlast0": 0,
    "schwellenwert0": 0,
    "schwellenwerte": np.array(
        [11_693, 19_134, 32_075, 62_080, 93_120, 1_000_000, np.inf],
    ),
    "marginale steuer": np.array([0, 0.2, 0.3, 0.41, 0.48, 0.5, 0.55]),
}

eink_vert_ö["steuerlast_eigenkreation"] = eink_vert_ö["einkommen"].apply(
    lambda x: einkommensteuer_österreich(
        x,
        tax_eigenkreation["steuerlast0"],
        tax_eigenkreation["schwellenwert0"],
        tax_eigenkreation["schwellenwerte"],
        tax_eigenkreation["marginale steuer"],
    ),
)
eink_vert_ö

Die folgende Zelle berechnet für Sie das Steueraufkommen Ihrer Eigenkreation und vergleicht es mit dem ursprünglichen Steueraufkommen.

steueraufkommen_e = eink_vert_ö["anzahl menschen"].dot(
    eink_vert_ö["steuerlast_eigenkreation"],
)
steueraufkommen_e, steueraufkommen_ö, np.round(steueraufkommen_e / steueraufkommen_ö, 2)

Um den Grenz-und Durchschnittssteuersatz zu plotten, benötigen wir wieder die Steuerlast in Abhängigkeit des Einkommens. Deshalb wird in der folgenden Zelle wie vorhin die Steuerlast für verschiedene Einkommen berechnet und wir verlassen unser Beispiel-Österreich mit 210 Menschen.

data_ö["steuerlast_e"] = data_ö["einkommen"].apply(
    lambda x: einkommensteuer_österreich(
        einkommen=x,
        steuerlast_min=tax_eigenkreation["steuerlast0"],
        schwellenwert_min=tax_eigenkreation["schwellenwert0"],
        schwellenwerte=tax_eigenkreation["schwellenwerte"],
        grenzsteuerlast=tax_eigenkreation["marginale steuer"],
    ),
)
data_ö

Berechnen und Plotten Sie jetzt den Durchschnittssteuersatz.

Berechnen und Plotten Sie jetzt den Grenzsteuersatz.

Aufgabe 4: Pentabilities (10min)#

Bitte bewerten Sie die Beiträge zur Gruppenarbeit in der Pentabilities-App. Bitte vergeben Sie über alle 5 Dimensionen hinweg Punkte für die Verhaltensweisen, welche Sie heute beobachten konnten. Denken Sie bitte daran, sowohl die Beiträge der Kommiliton:innen Ihrer Gruppe als auch Ihre eigenen zu bewerten.