From e0f9b853c9c76f20d069b3b26994776444ab2782 Mon Sep 17 00:00:00 2001 From: jdebacker Date: Wed, 31 Jan 2024 14:37:15 -0500 Subject: [PATCH 1/2] add notebook to produce figures used in NTA 2023 presentation --- examples/NTA_presentation_figures.ipynb | 673 ++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 examples/NTA_presentation_figures.ipynb diff --git a/examples/NTA_presentation_figures.ipynb b/examples/NTA_presentation_figures.ipynb new file mode 100644 index 0000000..02c9c30 --- /dev/null +++ b/examples/NTA_presentation_figures.ipynb @@ -0,0 +1,673 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# NTA 2023 Presentation Materials\n", + "This notebook contains the code used to generate the figures for the NTA 2023 presentation of DeBacker and Ryan (2023)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "import iot\n", + "from iot import iot_user\n", + "import numpy as np\n", + "import pandas as pd\n", + "import json\n", + "import plotly.express as px\n", + "import os\n", + "from plotly.colors import n_colors\n", + "from scipy.interpolate import UnivariateSpline\n", + "import plotly.graph_objects as go\n", + "\n", + "# set plotly template\n", + "template = \"plotly_white\"\n", + "COLOR_SEQUENCE = [\"red\", \"blue\"] # Republican, Democrat\n", + "dash_sequence = ['dash', 'dot', 'dashdot', \"solid\"] # 2012, 2016, 2020\n", + "\n", + "# Create path for plots to be saved to\n", + "CUR_DIR = os.getcwd()\n", + "path = os.path.join(CUR_DIR, \"plots\")\n", + "if not os.path.exists(path):\n", + " os.makedirs(path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Read in candidate platform JSON files\n", + "obama2015_path = \"https://raw.githubusercontent.com/jdebacker/examples/pres_proposals/psl_examples/taxcalc/Obama2015.json\"\n", + "romney2012_path = \"https://raw.githubusercontent.com/jdebacker/examples/pres_proposals/psl_examples/taxcalc/Romney2012.json\"\n", + "clinton2016_path = \"https://raw.githubusercontent.com/jdebacker/examples/pres_proposals/psl_examples/taxcalc/Clinton2016.json\"\n", + "trump2016_path = \"https://raw.githubusercontent.com/PSLmodels/examples/main/psl_examples/taxcalc/Trump2016.json\"\n", + "biden2020_path = \"https://raw.githubusercontent.com/PSLmodels/examples/main/psl_examples/taxcalc/Biden2020.json\"\n", + "trump2020_path = \"https://raw.githubusercontent.com/PSLmodels/examples/main/psl_examples/taxcalc/TCJA.json\"\n", + "\n", + "pre_2020_baseline = \"https://raw.githubusercontent.com/PSLmodels/examples/main/psl_examples/taxcalc/2017_law.json\"\n", + "baseline_2020 = \"https://raw.githubusercontent.com/PSLmodels/examples/main/psl_examples/taxcalc/TCJA.json\"\n", + "\n", + "\n", + "candidate_dict = {\n", + " \"Obama 2015\": {\"policy_path\": obama2015_path, \"baseline_path\": [pre_2020_baseline], \"start_year\": 2016},\n", + " \"Romney 2012\": {\"policy_path\": romney2012_path, \"baseline_path\": [pre_2020_baseline], \"start_year\": 2014}, #wanted to do 13, but taxcalc with CPS only goes to 13\n", + " \"Clinton 2016\": {\"policy_path\": clinton2016_path, \"baseline_path\": [pre_2020_baseline], \"start_year\": 2017},\n", + " \"Trump 2016\": {\"policy_path\": trump2016_path, \"baseline_path\": [pre_2020_baseline], \"start_year\": 2017},\n", + " \"Biden 2020\": {\"policy_path\": biden2020_path, \"baseline_path\": [pre_2020_baseline, baseline_2020], \"start_year\": 2021},\n", + " \"Trump 2020\": {\"policy_path\": trump2020_path, \"baseline_path\": [pre_2020_baseline], \"start_year\": 2021}}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create IOT objects for each candidate platform\n", + "policies = []\n", + "baseline_policies = []\n", + "labels = list(candidate_dict.keys())\n", + "# get years from start_year in candidate_dict\n", + "years = [v[\"start_year\"] for v in candidate_dict.values()]\n", + "for k, v in candidate_dict.items():\n", + " # with open(v[\"policy_path\"], \"r\") as file:\n", + " # json1 = file.read()\n", + " json1 = v[\"policy_path\"]#json.load(open(v[\"policy_path\"]))\n", + " print(json1)\n", + " policies.append(json1)\n", + " if v[\"baseline_path\"] is None:\n", + " json2 = {}\n", + " else:\n", + " for ii, vv in enumerate(v[\"baseline_path\"]):\n", + " list_json = []\n", + " # with open(vv, \"r\") as file:\n", + " # json2 = file.read()\n", + " # list_json.append(json2)\n", + " json2 = v[\"baseline_path\"]#open(v[\"baseline_path\"])\n", + " print(json2)\n", + " baseline_policies.append(list_json)\n", + "\n", + "iot_all = iot_user.iot_comparison(\n", + " policies=policies,\n", + " baseline_policies=baseline_policies,\n", + " labels=labels,\n", + " years=years,\n", + " data=\"CPS\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Plots of f(z) for each year/candidate\n", + "fplot = iot_all.plot(var=\"f\")\n", + "fplot.update_layout(\n", + " template=template,\n", + ")\n", + "fplot.write_image(\n", + " os.path.join(path, \"income_dist.png\")\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Plots of theta(z) for each year/candidate\n", + "theta_plot = iot_all.plot(var=\"theta_z\")\n", + "theta_plot.update_layout(\n", + " template=template,\n", + ")\n", + "theta_plot.write_image(\n", + " os.path.join(path, \"theta.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Plots of MTRs for each year/candidate\n", + "mtr_plot = iot_all.plot(var=\"mtr\")\n", + "mtr_plot.update_layout(\n", + " template=template,\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"blue\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"red\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"blue\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"blue\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "mtr_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "mtr_plot.write_image(\n", + " os.path.join(path, \"mtrs_all.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plots of g(z) for each year/candidate\n", + "gz_plot = iot_all.plot(var=\"g_z\")\n", + "gz_plot.update_layout(\n", + " template=template,\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"blue\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"red\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"blue\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"blue\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "# gz_plot.update_xaxes(range=[0, 850000])\n", + "\n", + "gz_plot.write_image(\n", + " os.path.join(path, \"gz_all.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plots of g(z) for each year/candidate, numerical approach\n", + "gz_plot = iot_all.plot(var=\"g_z_numerical\")\n", + "gz_plot.update_layout(\n", + " template=template,\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"blue\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"red\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"blue\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"blue\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "# gz_plot.update_xaxes(range=[0, 850000])\n", + "\n", + "gz_plot.write_image(\n", + " os.path.join(path, \"gz_numerical_all.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plots of g(z) for each year/candidate, numerical approach,\n", + "# HIGHlighting the Democrats\n", + "gz_plot = iot_all.plot(var=\"g_z_numerical\")\n", + "gz_plot.update_layout(\n", + " template=template,\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"blue\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"gray\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"blue\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"gray\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"blue\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"gray\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "# gz_plot.update_xaxes(range=[0, 850000])\n", + "\n", + "gz_plot.write_image(\n", + " os.path.join(path, \"gz_numerical_democrats.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plots of g(z) for each year/candidate, numerical approach\n", + "# HIGHlighting the Republicans\n", + "gz_plot = iot_all.plot(var=\"g_z_numerical\")\n", + "gz_plot.update_layout(\n", + " template=template,\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"gray\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"red\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"gray\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"gray\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "# gz_plot.update_xaxes(range=[0, 850000])\n", + "\n", + "gz_plot.write_image(\n", + " os.path.join(path, \"gz_numerical_republicans.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Show how MTRs vs tax base elasticity affecting g(z) for 2 candidates (separate plots,\n", + "# which will be put in a 2 panel figure)\n", + "fig = iot_all.JJZFig4(policy='Biden 2020')\n", + "fig.update_layout(\n", + " template=template,\n", + ")\n", + "# fig.update_xaxes(range=[0, 850000])\n", + "\n", + "fig.write_image(\n", + " os.path.join(path, \"composition_Biden2020_gz.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Loop over values of epsilon and plot Biden under these alternative values\"\n", + "eps_values = [0.2, 0.3, 0.4, 0.5, 0.6]\n", + "biden_eps_dict = {}\n", + "biden_eps_dict_numerical = {}\n", + "label_list = []\n", + "for i, v in enumerate(eps_values):\n", + " label = r\"$\\varepsilon$ = \" + str(v)\n", + " iot_b = iot_user.iot_comparison(\n", + " policies=[candidate_dict[\"Biden 2020\"][\"policy_path\"]],\n", + " baseline_policies=[candidate_dict[\"Biden 2020\"][\"baseline_path\"]],\n", + " labels=[label],\n", + " years=[candidate_dict[\"Biden 2020\"][\"start_year\"]],\n", + " eti=v,\n", + " data=\"CPS\"\n", + " )\n", + " label_list.append(label)\n", + " biden_eps_dict[v] = iot_b.iot[0].df().g_z\n", + " biden_eps_dict_numerical[v] = iot_b.iot[0].df().g_z_numerical" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plot each g_z\n", + "label_dict = {}\n", + "redVSblue = n_colors('rgb(0, 0, 255)', 'rgb(255, 0, 0)', len(label_list), colortype = 'rgb')\n", + "for i, v in enumerate(label_list):\n", + " label_dict[\"wide_variable_\" + str(i)] = str(eps_values[i])#v\n", + "fig = px.line(\n", + " x=iot_b.iot[0].df().z,\n", + " y=[\n", + " biden_eps_dict[0.2],\n", + " biden_eps_dict[0.3],\n", + " biden_eps_dict[0.4],\n", + " biden_eps_dict[0.5],\n", + " biden_eps_dict[0.6]\n", + " ],\n", + " color_discrete_sequence=redVSblue,\n", + " labels=label_dict)\n", + "fig.for_each_trace(lambda t: t.update(name = label_dict[t.name], legendgroup = label_dict[t.name],\n", + " hovertemplate = t.hovertemplate.replace(t.name, label_dict[t.name])))\n", + "fig.update_layout(\n", + " template=template,\n", + " xaxis_title=\"Wages and Salaries\",\n", + " yaxis_title=r\"$g_z$\",\n", + " legend=dict(\n", + " title=\"ETI value:\",\n", + " ),\n", + ")\n", + "\n", + "# fig.update_xaxes(range=[0, 850000])\n", + "fig.write_image(\n", + " os.path.join(path, \"vary_ETI_Biden2020_gz.png\"),\n", + " scale=4\n", + " )\n", + "\n", + "# plot each g_z_numerical\n", + "label_dict = {}\n", + "redVSblue = n_colors('rgb(0, 0, 255)', 'rgb(255, 0, 0)', len(label_list), colortype = 'rgb')\n", + "for i, v in enumerate(label_list):\n", + " label_dict[\"wide_variable_\" + str(i)] = str(eps_values[i])#v\n", + "fig = px.line(\n", + " x=iot_b.iot[0].df().z[50:],\n", + " y=[\n", + " biden_eps_dict_numerical[0.2][50:],\n", + " biden_eps_dict_numerical[0.3][50:],\n", + " biden_eps_dict_numerical[0.4][50:],\n", + " biden_eps_dict_numerical[0.5][50:],\n", + " biden_eps_dict_numerical[0.6][50:]\n", + " ],\n", + " color_discrete_sequence=redVSblue,\n", + " labels=label_dict)\n", + "fig.for_each_trace(lambda t: t.update(name = label_dict[t.name], legendgroup = label_dict[t.name],\n", + " hovertemplate = t.hovertemplate.replace(t.name, label_dict[t.name])))\n", + "fig.update_layout(\n", + " template=template,\n", + " xaxis_title=\"Wages and Salaries\",\n", + " yaxis_title=r\"$g_z$\",\n", + " legend=dict(\n", + " title=\"ETI value:\",\n", + " ),\n", + ")\n", + "\n", + "# fig.update_xaxes(range=[0, 850000])\n", + "fig.write_image(\n", + " os.path.join(path, \"vary_ETI_Biden2020_gz_numerical.png\"),\n", + " scale=4\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Redo above with varying epsilon(z) according to some empirical studies\n", + "# Required modification of model\n", + "eti_dict = {\n", + " \"eti_values\": [0.18, 0.106, 0.567, 1.83, 1.9],\n", + " \"knot_points\": [30000, 75000, 250000, 2000000, 10000000]\n", + "}\n", + "iot_all_vary = iot_user.iot_comparison(\n", + " policies=policies,\n", + " baseline_policies=baseline_policies,\n", + " labels=labels,\n", + " years=years,\n", + " eti=eti_dict,\n", + " data=\"CPS\"\n", + ")\n", + "# plots of g(z) for each year/candidate, numerical approach\n", + "gz_plot = iot_all_vary.plot(var=\"g_z_numerical\")\n", + "gz_plot.update_layout(\n", + " template=template,\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"blue\"),\n", + " selector=dict(name=\"Obama 2015\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dot\", color=\"red\"),\n", + " selector=dict(name=\"Romney 2012\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"blue\"),\n", + " selector=dict(name=\"Clinton 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"dash\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2016\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"blue\"),\n", + " selector=dict(name=\"Biden 2020\")\n", + ")\n", + "gz_plot.update_traces(\n", + " line=dict(dash=\"solid\", color=\"red\"),\n", + " selector=dict(name=\"Trump 2020\")\n", + ")\n", + "# gz_plot.update_xaxes(range=[0, 850000])\n", + "\n", + "gz_plot.write_image(\n", + " os.path.join(path, \"gz_numerical_all_vary_eti.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Plot how ETI varies with income\n", + "z_line = np.linspace(1, 1000000, 100000)\n", + "eti_dict = {\n", + " \"eti_values\": [0.18, 0.106, 0.567, 1.83, 1.9],\n", + " \"knot_points\": [30000, 75000, 250000, 2000000, 10000000]\n", + "}\n", + "eti_spl = UnivariateSpline(\n", + " eti_dict[\"knot_points\"], eti_dict[\"eti_values\"], k=3, s=0\n", + ")\n", + "eti = eti_spl(z_line)\n", + "fig = px.line(x=z_line, y=eti, labels={\"x\": \"Wages and Salaries\", \"y\": r\"$\\varepsilon$\"})\n", + "# add special markers without hoverinfo\n", + "fig.add_traces(\n", + " go.Scatter(\n", + " x=eti_dict[\"knot_points\"][:-2], y=eti_dict[\"eti_values\"][:-2], mode=\"markers\", name=\"Gruber and Saez (2022)\", hoverinfo=\"skip\"\n", + " )\n", + ")\n", + "# put legend at bottom\n", + "fig.update_layout(legend=dict(yanchor=\"bottom\", y=0.7, xanchor=\"left\", x=0.1))\n", + "fig.update_layout(\n", + " template=template,\n", + ")\n", + "fig.write_image(\n", + " os.path.join(path, \"ETI_spline.png\"),\n", + " scale=4,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Do experiment where hold constant g(z) - pick a candidate as baseline - then plot epsilon(z)\n", + "# that would recover those g(z) given the tax rates of each candidate\n", + "# one plot with epsilon(z) for each candidate\n", + "# Will pick Trump and Clinton (2016) for example\n", + "\n", + "# First, plot just their g(z)\n", + "fig = px.line(\n", + " x=iot_all.iot[2].df().z[10:],\n", + " y=[iot_all.iot[2].df().g_z_numerical[10:], iot_all.iot[3].df().g_z_numerical[10:]],\n", + " labels={\"x\": \"Wages and Salaries\", \"y\": r\"$g_z$\"},\n", + " )\n", + "fig.update_layout(\n", + " template=template,\n", + " legend=dict(\n", + " title=\"Candidate:\",\n", + " ),\n", + ")\n", + "candidate_name = [\"Clinton 2016\", \"Trump 2016\"]\n", + "label_dict = {}\n", + "for i, v in enumerate(candidate_name):\n", + " label_dict[\"wide_variable_\" + str(i)] = str(candidate_name[i])\n", + "fig.for_each_trace(lambda t: t.update(name = label_dict[t.name], legendgroup = label_dict[t.name],\n", + " hovertemplate = t.hovertemplate.replace(t.name, label_dict[t.name])))\n", + "\n", + "fig.write_image(\n", + " os.path.join(path, \"trump_clinton_g_z_numerical.png\"),\n", + " scale=4\n", + " )\n", + "# Now find the epsilon(z) that would give Trump's policies the same g(z) as Clinton\n", + "eti_beliefs_lw, eti_beliefs_jjz = iot.inverse_optimal_tax.find_eti(iot_all.iot[2], iot_all.iot[3], g_z_type=\"g_z\")\n", + "idx = np.where(np.absolute(eti_beliefs_jjz[1:]) < 10)[0]\n", + "fig2 = px.line(\n", + " x=iot_all.iot[2].df().z[idx],\n", + " y=eti_beliefs_jjz[idx],\n", + " labels={\"x\": \"Wages and Salaries\", \"y\": r\"$\\text{Implied } \\varepsilon$\"},\n", + " )\n", + "fig2.update_layout(\n", + " template=template,\n", + ")\n", + "fig2.write_image(\n", + " os.path.join(path, \"trump_eti.png\"),\n", + " scale=4\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "eti_dict = {\n", + " \"eti_values\": [0.18, 0.106, 0.567, 1.83, 1.9],\n", + " \"knot_points\": [30000, 75000, 250000, 2000000, 10000000]\n", + "}\n", + "# ETI values from Gruber and Saez (2002) (Table 3) and Saez (2004) (Tables 2, 4, 5)\n", + "# Compute MTR schedule under current law\n", + "iot_2023 = iot_user.iot_comparison(\n", + " policies=[{}],\n", + " baseline_policies=[None],\n", + " labels=[\"2023 Law\"],\n", + " years=[2023],\n", + " data=\"CPS\",\n", + " eti=eti_dict\n", + " )\n", + "fig = px.line(\n", + " x=iot_2023.iot[0].df().z,\n", + " y=iot_2023.iot[0].df().mtr\n", + " )\n", + "fig.update_layout(\n", + " template=template,\n", + " xaxis_title=\"Wages and Salaries\",\n", + " yaxis_title=r\"$T'(z)$\",\n", + ")\n", + "fig.write_image(\n", + " os.path.join(path, \"MTR_2023.png\"),\n", + " scale=4\n", + " )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "iot-dev", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 5337ce08ea9bf941f5ad3525340b61011786d05c Mon Sep 17 00:00:00 2001 From: jdebacker Date: Wed, 31 Jan 2024 14:37:44 -0500 Subject: [PATCH 2/2] avoid pandas deprecation --- iot/inverse_optimal_tax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iot/inverse_optimal_tax.py b/iot/inverse_optimal_tax.py index e5aff57..6e30f4d 100644 --- a/iot/inverse_optimal_tax.py +++ b/iot/inverse_optimal_tax.py @@ -135,7 +135,7 @@ def compute_mtr_dist( ) binned_data = pd.DataFrame( data[["mtr", income_measure, "z_bin", weight_var]] - .groupby(["z_bin"]) + .groupby(["z_bin"], observed=False) .apply(lambda x: wm(x[["mtr", income_measure]], x[weight_var])) ) # make column 0 into two columns