{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "\n", "# Visualizing the Taxes and Transfers System" ] }, { "cell_type": "markdown", "id": "1", "metadata": {}, "source": [ "## How to create a plot" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "To help you understand how GETTSIM works internally and how you are able to implement\n", "custom reforms, you can visualize the tax and transfer system. This tutorial explains\n", "how to create a graph and what information you can get from it." ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "import plotly.io as pio\n", "\n", "pio.renderers.default = \"notebook\"" ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "from gettsim import Labels, plot" ] }, { "cell_type": "markdown", "id": "5", "metadata": {}, "source": [ "The simplest way to create a plot is to use the `plot.dag.tt` function, passing only a policy date.\n", "\n", "Unfortunately, this is also unreadable due to the complexity of the tax and transfers system when looked at in its entirety." ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(policy_date_str=\"2025-01-01\")" ] }, { "cell_type": "markdown", "id": "7", "metadata": {}, "source": [ "Looking at the signature of `plot.dag.tt`, we see that it takes three types of arguments:\n", "\n", "- DAG-plotting options:\n", " - `primary_nodes`\n", " - `selection_type`\n", " - `selection_depth`\n", " - `include_params`\n", " - `show_node_description`\n", "- Arguments to `main`, which are the same as there\n", "- Any remaining keyword arguments are passed to `plotly.graph_objects.Figure.update`" ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt?" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "A more flexible way of looking at portions of the graph is to make use of the arguments\n", "`primary_nodes` and `selection_type` of `plot.dag.tt()`.\n", "\n", "## Focusing on a subset of the system using the plotting interface\n", "\n", "Primary nodes allow you to visualize only a subset of the complete graph of the tax and\n", "transfer systems. They can be passed to the `primary_nodes` argument of the\n", "`plot.dag.tt()` function. This is useful only in conjunction with specifying a selection\n", "type — in case you leave that out or set it to `None`, the complete graph is displayed\n", "(i.e., `primary_nodes` does not do anything).\n", "\n", "Other than `None`, `selection_type` may take one of four values:\n", "\n", "- `\"neighbors\"`: The neighbors (parents and children) of the primary nodes are displayed.\n", "- `\"descendants\"`: All descendants of the primary nodes are displayed.\n", "- `\"ancestors\"`: All ancestors of the primary nodes are displayed.\n", "- `\"all_paths\"`: All paths between the primary nodes are displayed (including any other\n", " nodes lying on these paths). You must pass at least two primary nodes.\n", "\n", "We'll go through these in turn.\n", "\n", "### Selection type: Neighbors\n", "\n", "This is the example above. We pick one primary node (`\"betrag_y_sn\"` in the\n", "`\"einkommensteuer\"` / `\"abgeltungssteuer\"` namespace) and it is displayed together with\n", "its parents (`\"zu_versteuernde_kapitalerträge_y_sn\"` and `\"satz\"` in the same namespace)\n", "and its child (`\"betrag_y_sn\"` in the `\"solidaritätszuschlag\"` namespace)." ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"neighbors\",\n", ")" ] }, { "cell_type": "markdown", "id": "11", "metadata": {}, "source": [ "By changing the `selection_depth` argument from its default of 1 for neighbors, you can look at a broader vicinity in both directions. Setting it to 2 will include all grandparents and grandchildren, and so on." ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"neighbors\",\n", " selection_depth=2,\n", ")" ] }, { "cell_type": "markdown", "id": "13", "metadata": {}, "source": [ "### Selection type: Ancestors\n", "\n", "This takes a node and plots it along with **all** of its ancestors. Picking again\n", "`\"betrag_y_sn\"` in the `\"einkommensteuer\"` / `\"abgeltungssteuer\"` namespace, we get its\n", "two parents as above. Among them, `\"satz\"` has no ancestors because it is a parameter of\n", "the tax system. However, `\"zu_versteuernde_kapitalerträge_y_sn\"` has a much longer set\n", "of preceding nodes, for setting up the tax unit from primitives (marital status, joint\n", "filing) and calculating the taxable portion of all capital income." ] }, { "cell_type": "code", "execution_count": null, "id": "14", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"ancestors\",\n", ")" ] }, { "cell_type": "markdown", "id": "15", "metadata": {}, "source": [ "Again, we can use the `selection_depth` argument to control how many levels of the graph we look at:" ] }, { "cell_type": "code", "execution_count": null, "id": "16", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"ancestors\",\n", " selection_depth=3,\n", ")" ] }, { "cell_type": "markdown", "id": "17", "metadata": {}, "source": [ "As it happens, this is the same (up to possible layout differences) as letting the graph know that\n", "`sn_id` is an input column:" ] }, { "cell_type": "code", "execution_count": null, "id": "18", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"ancestors\",\n", " labels=Labels(input_columns=[\"sn_id\"]),\n", " include_warn_nodes=False,\n", ")" ] }, { "cell_type": "markdown", "id": "19", "metadata": {}, "source": [ "### Selection type: Descendants\n", "\n", "This takes a node and plots it along with **all** of its descendants. Picking again\n", "`\"betrag_y_sn\"` in the `\"einkommensteuer\"` / `\"abgeltungssteuer\"` namespace and , we get a\n", "long DAG describing its descendants because the amount of Solidaritätszuschlag paid\n", "impacts the means-tested transfers Bürgergeld, Wohngeld, and Kinderzuschlag." ] }, { "cell_type": "code", "execution_count": null, "id": "20", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\"einkommensteuer__abgeltungssteuer__betrag_y_sn\"],\n", " selection_type=\"descendants\",\n", ")" ] }, { "cell_type": "markdown", "id": "21", "metadata": {}, "source": [ "### Selection type: All paths\n", "\n", "This takes a set of nodes and plots all paths connecting them, along with any nodes\n", "lying on these paths. This can be very useful to understand the connections between two\n", "or more nodes. Picking again `\"betrag_y_sn\"` in the `\"einkommensteuer\"` /\n", "`\"abgeltungssteuer\"` namespace, we additionally add `\"betrag_m_bg\"` in the\n", "`\"bürgergeld\"` namespace.\n", "\n", "This ends up being almost the same as the previous example, except that unrelated nodes\n", "(those in the `\"grundsicherung_im_alter\"` namespace and the amounts of Wohngeld and\n", "Kinderzuschlag) are not displayed." ] }, { "cell_type": "code", "execution_count": null, "id": "22", "metadata": {}, "outputs": [], "source": [ "plot.dag.tt(\n", " policy_date_str=\"2025-01-01\",\n", " primary_nodes=[\n", " \"einkommensteuer__abgeltungssteuer__betrag_y_sn\",\n", " \"bürgergeld__betrag_m_bg\",\n", " ],\n", " selection_type=\"all_paths\",\n", ")" ] } ], "metadata": { "hide_input": false, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": false, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "304px" }, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }