Extend#
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.
To use the extend feature, set the label_to_extend
class attribute to the label that should be extended.
Example#
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.
import paramtools
class TaxParams(paramtools.Parameters):
defaults = {
"schema": {
"labels": {
"year": {
"type": "int",
"validators": {"range": {"min": 2013, "max": 2027}}
},
"marital_status": {
"type": "str",
"validators": {"choice": {"choices": ["single", "joint"]}}
},
}
},
"standard_deduction": {
"title": "Standard deduction amount",
"description": "Amount filing unit can use as a standard deduction.",
"type": "float",
"value": [
{"year": 2017, "marital_status": "single", "value": 6350},
{"year": 2017, "marital_status": "joint", "value": 12700},
{"year": 2018, "marital_status": "single", "value": 12000},
{"year": 2018, "marital_status": "joint", "value": 24000},
{"year": 2026, "marital_status": "single", "value": 7685},
{"year": 2026, "marital_status": "joint", "value": 15369}],
"validators": {
"range": {
"min": 0,
"max": 9e+99
}
}
},
}
label_to_extend = "year"
array_first = True
params = TaxParams()
params.standard_deduction
array([[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[12000., 24000.],
[ 7685., 15369.],
[ 7685., 15369.]])
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:
params.adjust(
{
"standard_deduction": [
{"year": 2017, "value": 10000},
{"year": 2020, "marital_status": "single", "value": 15000},
{"year": 2021, "marital_status": "joint", "value": 20000}
]
}
)
params.standard_deduction
array([[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[10000., 10000.],
[10000., 10000.],
[10000., 10000.],
[15000., 10000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.]])
Clobber#
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:
params = TaxParams()
params.adjust(
{
"standard_deduction": [
{"year": 2017, "value": 10000},
{"year": 2020, "marital_status": "single", "value": 15000},
{"year": 2021, "marital_status": "joint", "value": 20000}
]
},
clobber=False,
)
params.standard_deduction
array([[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[ 6350., 12700.],
[10000., 10000.],
[12000., 24000.],
[12000., 24000.],
[15000., 24000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[15000., 20000.],
[ 7685., 15369.],
[ 7685., 15369.]])
Extend behavior by validator#
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.
Note: You can view the grid of values for any label by inspecting the label_grid
attribute of a paramtools.Parameters
derived instance.
Range#
Type: int
{
"range": { "min": 0, "max": 5 }
}
Extend values:
[0, 1, 2, 3, 4, 5]
Type: float
{
"range": { "min": 0, "max": 2, "step": 0.5 }
}
Extend values:
[0, 0.5, 1.0, 1.5, 2.0]
Type: date
{
"range": { "min": "2019-01-01", "max": "2019-01-05", "step": { "days": 2 } }
}
Extend values:
[datetime.date(2019, 1, 1),
datetime.date(2019, 1, 3),
datetime.date(2019, 1, 5)]
Choice#
Type: int
{
"choice": { "choices": [-1, -2, -3] }
}
Extend values:
[-1, -2, -3]
Type: str
{
"choice": { "choices": ["january", "february", "march"] }
}
Extend values:
["january", "february", "march"]