{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Extend\n", "\n", "The values of a parameter can be extended along a specified label. This is helpful when a parameter's values are the same for different values of a label and there is some inherent order in that label. The extend feature allows you to simply write down the minimum amount of information needed to fill in a parameter's values and ParamTools will fill in the gaps.\n", "\n", "To use the extend feature, set the `label_to_extend` class attribute to the label that should be extended.\n", "\n", "## Example\n", "\n", "The standard deduction parameter's values only need to be specified when there is a change in the tax law. For the other years, it does not change (unless its indexed to inflation). It would be annoying to have to manually write out each of its values. Instead, we can more concisely write its values in 2017, its new values in 2018 after the TCJA tax reform was passed, and its values after provisions of the TCJA are phased out in 2026.\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [ 7685., 15369.],\n", " [ 7685., 15369.]])" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import paramtools\n", "\n", "\n", "class TaxParams(paramtools.Parameters):\n", " defaults = {\n", " \"schema\": {\n", " \"labels\": {\n", " \"year\": {\n", " \"type\": \"int\",\n", " \"validators\": {\"range\": {\"min\": 2013, \"max\": 2027}}\n", " },\n", " \"marital_status\": {\n", " \"type\": \"str\",\n", " \"validators\": {\"choice\": {\"choices\": [\"single\", \"joint\"]}}\n", " },\n", " }\n", " },\n", " \"standard_deduction\": {\n", " \"title\": \"Standard deduction amount\",\n", " \"description\": \"Amount filing unit can use as a standard deduction.\",\n", " \"type\": \"float\",\n", " \"value\": [\n", " {\"year\": 2017, \"marital_status\": \"single\", \"value\": 6350},\n", " {\"year\": 2017, \"marital_status\": \"joint\", \"value\": 12700},\n", " {\"year\": 2018, \"marital_status\": \"single\", \"value\": 12000},\n", " {\"year\": 2018, \"marital_status\": \"joint\", \"value\": 24000},\n", " {\"year\": 2026, \"marital_status\": \"single\", \"value\": 7685},\n", " {\"year\": 2026, \"marital_status\": \"joint\", \"value\": 15369}],\n", " \"validators\": {\n", " \"range\": {\n", " \"min\": 0,\n", " \"max\": 9e+99\n", " }\n", " }\n", " },\n", " }\n", "\n", " label_to_extend = \"year\"\n", " array_first = True\n", "\n", "params = TaxParams()\n", "params.standard_deduction\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Adjustments are also extended along `label_to_extend`. In the example below, `standard_deduction` is set to 10,000 in 2017, increased to 15,000 for single tax units in 2020, and increased to 20,000 for joint tax units in 2021:\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [10000., 10000.],\n", " [10000., 10000.],\n", " [10000., 10000.],\n", " [15000., 10000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.]])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "params.adjust(\n", " {\n", " \"standard_deduction\": [\n", " {\"year\": 2017, \"value\": 10000},\n", " {\"year\": 2020, \"marital_status\": \"single\", \"value\": 15000},\n", " {\"year\": 2021, \"marital_status\": \"joint\", \"value\": 20000}\n", " ]\n", " }\n", ")\n", "\n", "params.standard_deduction\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Clobber\n", "\n", "In the previous example, the new values _clobber_ the existing values in years after they are specified. By setting `clobber` to `False`, only values that were added automatically will be replaced by the new ones. User defined values such as those in 2026 will not be over-written by the new values:\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [ 6350., 12700.],\n", " [10000., 10000.],\n", " [12000., 24000.],\n", " [12000., 24000.],\n", " [15000., 24000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [15000., 20000.],\n", " [ 7685., 15369.],\n", " [ 7685., 15369.]])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "params = TaxParams()\n", "params.adjust(\n", " {\n", " \"standard_deduction\": [\n", " {\"year\": 2017, \"value\": 10000},\n", " {\"year\": 2020, \"marital_status\": \"single\", \"value\": 15000},\n", " {\"year\": 2021, \"marital_status\": \"joint\", \"value\": 20000}\n", " ]\n", " },\n", " clobber=False,\n", ")\n", "\n", "params.standard_deduction\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extend behavior by validator\n", "\n", "ParamTools uses the validator associated with `label_to_extend` to determine how values should be extended by assuming that there is some order among the range of possible values for the label.\n", "\n", "Note: You can view the grid of values for any label by inspecting the `label_grid` attribute of a `paramtools.Parameters` derived instance.\n", "\n", "### Range\n", "\n", "**Type:** `int`\n", "\n", "```json\n", "{\n", " \"range\": { \"min\": 0, \"max\": 5 }\n", "}\n", "```\n", "\n", "_Extend values:_\n", "\n", "```python\n", "[0, 1, 2, 3, 4, 5]\n", "```\n", "\n", "**Type:** `float`\n", "\n", "```json\n", "{\n", " \"range\": { \"min\": 0, \"max\": 2, \"step\": 0.5 }\n", "}\n", "```\n", "\n", "_Extend values:_\n", "\n", "```python\n", "[0, 0.5, 1.0, 1.5, 2.0]\n", "```\n", "\n", "**Type:** `date`\n", "\n", "```json\n", "{\n", " \"range\": { \"min\": \"2019-01-01\", \"max\": \"2019-01-05\", \"step\": { \"days\": 2 } }\n", "}\n", "```\n", "\n", "_Extend values:_\n", "\n", "```python\n", "[datetime.date(2019, 1, 1),\n", " datetime.date(2019, 1, 3),\n", " datetime.date(2019, 1, 5)]\n", "```\n", "\n", "### Choice\n", "\n", "**Type:** `int`\n", "\n", "```json\n", "{\n", " \"choice\": { \"choices\": [-1, -2, -3] }\n", "}\n", "```\n", "\n", "_Extend values:_\n", "\n", "```python\n", "[-1, -2, -3]\n", "```\n", "\n", "**Type:** `str`\n", "\n", "```json\n", "{\n", " \"choice\": { \"choices\": [\"january\", \"february\", \"march\"] }\n", "}\n", "```\n", "\n", "_Extend values:_\n", "\n", "```python\n", "[\"january\", \"february\", \"march\"]\n", "```\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }