taxcalc 5.3.0__py3-none-any.whl → 6.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taxcalc/__init__.py +1 -1
- taxcalc/calcfunctions.py +11 -11
- taxcalc/calculator.py +1 -1
- taxcalc/cli/tc.py +1 -8
- taxcalc/data.py +1 -2
- taxcalc/policy.py +7 -22
- taxcalc/policy_current_law.json +6 -6
- taxcalc/records.py +78 -82
- taxcalc/records_variables.json +106 -106
- taxcalc/reforms/2017_law.json +1 -1
- taxcalc/reforms/ARPA.json +1 -1
- taxcalc/reforms/Renacci.json +1 -1
- taxcalc/reforms/TCJA.json +1 -1
- taxcalc/reforms/Trump2016.json +1 -1
- taxcalc/reforms/Trump2017.json +1 -1
- taxcalc/taxcalcio.py +60 -51
- taxcalc/tests/conftest.py +19 -14
- taxcalc/tests/reforms.json +1 -1
- taxcalc/tests/reforms_expect.csv +54 -54
- taxcalc/tests/test_4package.py +3 -15
- taxcalc/tests/test_calcfunctions.py +2 -2
- taxcalc/tests/test_calculator.py +197 -160
- taxcalc/tests/test_cpscsv.py +0 -22
- taxcalc/tests/test_data.py +11 -3
- taxcalc/tests/test_parameters.py +42 -0
- taxcalc/tests/test_records.py +139 -8
- taxcalc/tests/test_reforms.py +5 -7
- taxcalc/tests/test_taxcalcio.py +3 -58
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/METADATA +1 -1
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/RECORD +34 -40
- taxcalc/puf_ratios.csv +0 -26
- taxcalc/puf_weights.csv.gz +0 -0
- taxcalc/tests/test_compare.py +0 -330
- taxcalc/tests/test_compatible_data.py +0 -334
- taxcalc/tests/test_puf_var_stats.py +0 -194
- taxcalc/tests/test_pufcsv.py +0 -328
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/WHEEL +0 -0
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/entry_points.txt +0 -0
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/licenses/LICENSE +0 -0
- {taxcalc-5.3.0.dist-info → taxcalc-6.1.0.dist-info}/top_level.txt +0 -0
taxcalc/__init__.py
CHANGED
taxcalc/calcfunctions.py
CHANGED
@@ -1871,7 +1871,7 @@ def AMT(e07300, dwks13, standard, f6251, c00100, c18300, taxbc,
|
|
1871
1871
|
dwks14, c05700, e62900, e00700, dwks10, age_head, age_spouse,
|
1872
1872
|
earned, cmbtp, qbided,
|
1873
1873
|
AMT_child_em_c_age, AMT_brk1,
|
1874
|
-
AMT_em, AMT_prt, AMT_rt1,
|
1874
|
+
AMT_em, AMT_prt, AMT_rt1, AMT_rt2_addon,
|
1875
1875
|
AMT_child_em, AMT_em_ps, AMT_em_pe,
|
1876
1876
|
AMT_CG_brk1, AMT_CG_brk2, AMT_CG_brk3, AMT_CG_rt1, AMT_CG_rt2,
|
1877
1877
|
AMT_CG_rt3, AMT_CG_rt4, c05800, c09600, c62100):
|
@@ -1946,8 +1946,8 @@ def AMT(e07300, dwks13, standard, f6251, c00100, c18300, taxbc,
|
|
1946
1946
|
AMT exemption phaseout rate
|
1947
1947
|
AMT_rt1: float
|
1948
1948
|
AMT rate 1
|
1949
|
-
|
1950
|
-
Additional AMT rate for AMT taxable income
|
1949
|
+
AMT_rt2_addon: float
|
1950
|
+
Additional AMT rate for AMT taxable income above AMT bracket 1
|
1951
1951
|
AMT_child_em: float
|
1952
1952
|
Child AMT exemption additional income base
|
1953
1953
|
AMT_em_ps: list
|
@@ -1977,14 +1977,14 @@ def AMT(e07300, dwks13, standard, f6251, c00100, c18300, taxbc,
|
|
1977
1977
|
c09600: float
|
1978
1978
|
Alternative Minimum Tax (AMT) liability
|
1979
1979
|
c62100: float
|
1980
|
-
Alternative Minimum Tax (AMT)
|
1980
|
+
Alternative Minimum Tax (AMT) taxable income
|
1981
1981
|
|
1982
1982
|
Returns
|
1983
1983
|
-------
|
1984
1984
|
c62100: float
|
1985
|
-
Alternative Minimum Tax (AMT)
|
1985
|
+
Alternative Minimum Tax (AMT) taxable income
|
1986
1986
|
c09600: float
|
1987
|
-
Alternative Minimum Tax (AMT) liability
|
1987
|
+
Alternative Minimum Tax (AMT) tax liability
|
1988
1988
|
c05800: float
|
1989
1989
|
Total (regular + AMT) income tax liability before credits
|
1990
1990
|
"""
|
@@ -2012,7 +2012,7 @@ def AMT(e07300, dwks13, standard, f6251, c00100, c18300, taxbc,
|
|
2012
2012
|
line29 = min(line29, earned + AMT_child_em)
|
2013
2013
|
line30 = max(0., c62100 - line29)
|
2014
2014
|
line3163 = (AMT_rt1 * line30 +
|
2015
|
-
|
2015
|
+
AMT_rt2_addon * max(0., (line30 - (AMT_brk1 / sep))))
|
2016
2016
|
if dwks10 > 0. or dwks13 > 0. or dwks14 > 0. or dwks19 > 0. or e24515 > 0.:
|
2017
2017
|
# complete Form 6251, Part III (line36 is equal to line30)
|
2018
2018
|
line37 = dwks13
|
@@ -2021,7 +2021,7 @@ def AMT(e07300, dwks13, standard, f6251, c00100, c18300, taxbc,
|
|
2021
2021
|
line40 = min(line30, line39)
|
2022
2022
|
line41 = max(0., line30 - line40)
|
2023
2023
|
line42 = (AMT_rt1 * line41 +
|
2024
|
-
|
2024
|
+
AMT_rt2_addon * max(0., (line41 - (AMT_brk1 / sep))))
|
2025
2025
|
line44 = dwks14
|
2026
2026
|
line45 = max(0., AMT_CG_brk1[MARS - 1] - line44)
|
2027
2027
|
line46 = min(line30, line37)
|
@@ -2268,7 +2268,7 @@ def EITCamount(basic_frac, phasein_rate, earnings, max_amount,
|
|
2268
2268
|
@iterate_jit(nopython=True)
|
2269
2269
|
def EITC(MARS, DSI, EIC, c00100, e00300, e00400, e00600, c01000,
|
2270
2270
|
e02000, e26270, age_head, age_spouse, earned, earned_p, earned_s,
|
2271
|
-
EITC_ps, EITC_MinEligAge, EITC_MaxEligAge,
|
2271
|
+
EITC_ps, EITC_MinEligAge, EITC_MaxEligAge, EITC_ps_addon_MarriedJ,
|
2272
2272
|
EITC_rt, EITC_c, EITC_prt, EITC_basic_frac,
|
2273
2273
|
EITC_InvestIncome_c, EITC_excess_InvestIncome_rt,
|
2274
2274
|
EITC_indiv, EITC_sep_filers_elig, c59660):
|
@@ -2315,7 +2315,7 @@ def EITC(MARS, DSI, EIC, c00100, e00300, e00400, e00600, c01000,
|
|
2315
2315
|
Minimum age for childless EITC eligibility
|
2316
2316
|
EITC_MaxEligAge: int
|
2317
2317
|
Maximum age for childless EITC eligibility
|
2318
|
-
|
2318
|
+
EITC_ps_addon_MarriedJ: list
|
2319
2319
|
Extra earned income credit phaseout start AGI for
|
2320
2320
|
married filling jointly
|
2321
2321
|
EITC_rt: list
|
@@ -2360,7 +2360,7 @@ def EITC(MARS, DSI, EIC, c00100, e00300, e00400, e00600, c01000,
|
|
2360
2360
|
c59660 = eitc
|
2361
2361
|
|
2362
2362
|
if MARS == 2:
|
2363
|
-
po_start = EITC_ps[EIC] +
|
2363
|
+
po_start = EITC_ps[EIC] + EITC_ps_addon_MarriedJ[EIC]
|
2364
2364
|
if not EITC_indiv:
|
2365
2365
|
# filing unit EITC rather than individual EITC
|
2366
2366
|
eitc = EITCamount(EITC_basic_frac,
|
taxcalc/calculator.py
CHANGED
@@ -81,7 +81,7 @@ class Calculator():
|
|
81
81
|
The most efficient way to specify current-law and reform Calculator
|
82
82
|
objects is as follows:
|
83
83
|
pol = Policy()
|
84
|
-
rec = Records()
|
84
|
+
rec = Records.cps_constructor()
|
85
85
|
calc1 = Calculator(policy=pol, records=rec) # current-law
|
86
86
|
pol.implement_reform(...)
|
87
87
|
calc2 = Calculator(policy=pol, records=rec) # reform
|
taxcalc/cli/tc.py
CHANGED
@@ -229,12 +229,6 @@ def cli_tc_main():
|
|
229
229
|
sys.stderr.write(msg)
|
230
230
|
sys.stderr.write('USAGE: tc --help\n')
|
231
231
|
return 1
|
232
|
-
# specify if aging input data
|
233
|
-
aging_data = (
|
234
|
-
inputfn.endswith('puf.csv') or
|
235
|
-
inputfn.endswith('cps.csv') or
|
236
|
-
inputfn.endswith('tmd.csv')
|
237
|
-
)
|
238
232
|
# check args.dumpdb and args.dumpvars consistency
|
239
233
|
if not args.dumpdb and args.dumpvars:
|
240
234
|
msg = 'ERROR: DUMPVARS file specified without --dumpdb option\n'
|
@@ -299,7 +293,6 @@ def cli_tc_main():
|
|
299
293
|
baseline=args.baseline,
|
300
294
|
reform=args.reform,
|
301
295
|
assump=args.assump,
|
302
|
-
aging_input_data=aging_data,
|
303
296
|
exact_calculations=args.exact,
|
304
297
|
)
|
305
298
|
if tcio.errmsg:
|
@@ -346,7 +339,7 @@ def cli_tc_main():
|
|
346
339
|
return 0
|
347
340
|
# analyze years after taxyear if args.numyears is greater than one
|
348
341
|
for xyear in range(1, args.numyears):
|
349
|
-
tcio.advance_to_year(taxyear + xyear
|
342
|
+
tcio.advance_to_year(taxyear + xyear)
|
350
343
|
tcio.analyze(
|
351
344
|
output_params=args.params,
|
352
345
|
output_tables=args.tables,
|
taxcalc/data.py
CHANGED
@@ -236,8 +236,7 @@ class Data():
|
|
236
236
|
self.IGNORED_VARS.add(varname)
|
237
237
|
# check that MUST_READ_VARS are all present in taxdf
|
238
238
|
if not self.MUST_READ_VARS.issubset(READ_VARS):
|
239
|
-
|
240
|
-
raise ValueError(msg)
|
239
|
+
raise ValueError('data missing one or more MUST_READ_VARS')
|
241
240
|
# delete intermediate taxdf object
|
242
241
|
del taxdf
|
243
242
|
# create other class variables that are set to all zeros
|
taxcalc/policy.py
CHANGED
@@ -7,7 +7,6 @@ Tax-Calculator federal tax policy Policy class.
|
|
7
7
|
|
8
8
|
import os
|
9
9
|
import json
|
10
|
-
from pathlib import Path
|
11
10
|
import paramtools
|
12
11
|
from taxcalc.parameters import Parameters
|
13
12
|
from taxcalc.growfactors import GrowFactors
|
@@ -56,8 +55,7 @@ class Policy(Parameters):
|
|
56
55
|
return last_budget_year - Policy.JSON_START_YEAR + 1
|
57
56
|
|
58
57
|
# NOTE: the following three data structures use internal parameter names:
|
59
|
-
# (1) specify which Policy parameters have been removed or renamed
|
60
|
-
# where "recently" means in the last major release
|
58
|
+
# (1) specify which Policy parameters have been removed or renamed
|
61
59
|
REMOVED_PARAMS = {
|
62
60
|
# following parameters were renamed in PR 2918
|
63
61
|
'SS_thd50': 'was renamed SS_thd1 in Tax-Calculator 5.0.0',
|
@@ -111,9 +109,13 @@ class Policy(Parameters):
|
|
111
109
|
'ID_reduction_other_rate': (
|
112
110
|
'was renamed ID_reduction_rate in Tax-Calculator 5.1.0'
|
113
111
|
),
|
112
|
+
# following parameters were renamed in PR 2965
|
113
|
+
'AMT_rt2': 'was renamed AMT_rt2_addon in Tax-Calculator 6.1.0',
|
114
|
+
'EITC_ps_MarriedJ': (
|
115
|
+
'was renamed EITC_ps_addon_MarriedJ in Tax-Calculator 6.1.0'
|
116
|
+
),
|
114
117
|
}
|
115
|
-
# (2) specify which Policy parameters have been redefined
|
116
|
-
# where "recently" means in the last major release
|
118
|
+
# (2) specify which Policy parameters have been redefined
|
117
119
|
REDEFINED_PARAMS = {}
|
118
120
|
# (3) specify which Policy parameters are wage (rather than price) indexed
|
119
121
|
WAGE_INDEXED_PARAMS = ['SS_Earnings_c', 'SS_Earnings_thd']
|
@@ -141,23 +143,6 @@ class Policy(Parameters):
|
|
141
143
|
Policy.REDEFINED_PARAMS,
|
142
144
|
Policy.WAGE_INDEXED_PARAMS, **kwargs)
|
143
145
|
|
144
|
-
@staticmethod
|
145
|
-
def tmd_constructor(
|
146
|
-
growfactors: Path | GrowFactors,
|
147
|
-
last_budget_year=LAST_BUDGET_YEAR,
|
148
|
-
): # pragma: no cover
|
149
|
-
"""
|
150
|
-
Static method returns a Policy object instantiated with TMD
|
151
|
-
input data. This convenience method works in a analogous way
|
152
|
-
to Policy(), which returns a Policy object instantiated with
|
153
|
-
non-TMD input data.
|
154
|
-
"""
|
155
|
-
if isinstance(growfactors, Path):
|
156
|
-
growfactors = GrowFactors(growfactors_filename=str(growfactors))
|
157
|
-
else:
|
158
|
-
assert isinstance(growfactors, GrowFactors)
|
159
|
-
return Policy(gfactors=growfactors, last_budget_year=last_budget_year)
|
160
|
-
|
161
146
|
@staticmethod
|
162
147
|
def read_json_reform(obj):
|
163
148
|
"""
|
taxcalc/policy_current_law.json
CHANGED
@@ -17502,9 +17502,9 @@
|
|
17502
17502
|
"cps": true
|
17503
17503
|
}
|
17504
17504
|
},
|
17505
|
-
"
|
17505
|
+
"AMT_rt2_addon": {
|
17506
17506
|
"title": "Additional AMT rate for AMT taxable income above AMT bracket 1",
|
17507
|
-
"description": "The additional tax rate applied to the portion of AMT income above the AMT bracket 1.",
|
17507
|
+
"description": "The additional tax rate applied to the portion of AMT income above the AMT bracket 1, which means that AMT_rt2_addon equals AMT_rt2 minus AMT_rt1.",
|
17508
17508
|
"notes": "This is the additional tax rate (on top of AMT rate 1) for AMT income above AMT bracket 1.",
|
17509
17509
|
"section_1": "Personal Income",
|
17510
17510
|
"section_2": "Alternative Minimum Tax",
|
@@ -17519,8 +17519,8 @@
|
|
17519
17519
|
],
|
17520
17520
|
"validators": {
|
17521
17521
|
"range": {
|
17522
|
-
"min": 0,
|
17523
|
-
"max": 1
|
17522
|
+
"min": 0.0,
|
17523
|
+
"max": 0.1
|
17524
17524
|
}
|
17525
17525
|
},
|
17526
17526
|
"compatible_data": {
|
@@ -19734,9 +19734,9 @@
|
|
19734
19734
|
"cps": true
|
19735
19735
|
}
|
19736
19736
|
},
|
19737
|
-
"
|
19737
|
+
"EITC_ps_addon_MarriedJ": {
|
19738
19738
|
"title": "Extra earned income credit phaseout start AGI for married filling jointly",
|
19739
|
-
"description": "This is the additional amount added on the regular phaseout start amount for taxpayers with filling status of married filing jointly.",
|
19739
|
+
"description": "This is the additional amount added on the regular phaseout start amount for taxpayers with filling status of married filing jointly, which means that EITC_ps_addon_MarriedJ equals EITC_ps_MarriedJ minus EITC_ps.",
|
19740
19740
|
"notes": "",
|
19741
19741
|
"section_1": "Refundable Credits",
|
19742
19742
|
"section_2": "Earned Income Tax Credit",
|
taxcalc/records.py
CHANGED
@@ -23,10 +23,10 @@ class Records(Data):
|
|
23
23
|
|
24
24
|
Parameters
|
25
25
|
----------
|
26
|
-
data: string or Pandas DataFrame
|
26
|
+
data: string or Pandas DataFrame or None
|
27
27
|
string describes CSV file in which records data reside;
|
28
28
|
DataFrame already contains records data;
|
29
|
-
default value is
|
29
|
+
default value is None.
|
30
30
|
NOTE: when using custom data, set this argument to a DataFrame.
|
31
31
|
NOTE: to use your own data for a specific year with Tax-Calculator,
|
32
32
|
be sure to read the documentation on creating your own data file and
|
@@ -37,29 +37,28 @@ class Records(Data):
|
|
37
37
|
NOTE: data=None is allowed but the returned instance contains only
|
38
38
|
the data variable information in the specified VARINFO file.
|
39
39
|
|
40
|
-
start_year: integer
|
40
|
+
start_year: integer or None
|
41
41
|
specifies calendar year of the input data;
|
42
|
-
|
42
|
+
default value is None.
|
43
43
|
Note that if specifying your own data (see above NOTE) as being
|
44
44
|
a custom data set, be sure to explicitly set start_year to the
|
45
45
|
custom data's calendar year.
|
46
46
|
|
47
47
|
gfactors: GrowFactors class instance or None
|
48
48
|
containing record data growth (or extrapolation) factors.
|
49
|
+
default value is None.
|
49
50
|
|
50
|
-
weights:
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
default value is filename of the PUF weights.
|
51
|
+
weights: Pandas DataFrame or None
|
52
|
+
DataFrame contains data weights;
|
53
|
+
None creates empty weights DataFrame;
|
54
|
+
default value is None
|
55
55
|
NOTE: when using custom weights, set this argument to a DataFrame.
|
56
56
|
NOTE: see weights_scale documentation below.
|
57
57
|
|
58
|
-
adjust_ratios:
|
59
|
-
|
60
|
-
DataFrame already contains transposed/no-index adjustment ratios;
|
58
|
+
adjust_ratios: Pandas DataFrame or None
|
59
|
+
DataFrame contains transposed/no-index adjustment ratios;
|
61
60
|
None creates empty adjustment-ratios DataFrame;
|
62
|
-
default value is
|
61
|
+
default value is None.
|
63
62
|
NOTE: when using custom ratios, set this argument to a DataFrame.
|
64
63
|
NOTE: if specifying a DataFrame, set adjust_ratios to my_df defined as:
|
65
64
|
my_df = pd.read_csv('<my_ratios.csv>', index_col=0).transpose()
|
@@ -75,6 +74,7 @@ class Records(Data):
|
|
75
74
|
generated in the taxdata repository use a weights_scale of 0.01,
|
76
75
|
while TMD input data generated in the tax-microdata repository
|
77
76
|
use a 1.0 weights_scale value.
|
77
|
+
default value is 0.01.
|
78
78
|
|
79
79
|
Raises
|
80
80
|
------
|
@@ -92,20 +92,12 @@ class Records(Data):
|
|
92
92
|
|
93
93
|
Notes
|
94
94
|
-----
|
95
|
-
Typical usage when using PUF input data is as follows::
|
96
|
-
|
97
|
-
recs = Records()
|
98
|
-
|
99
|
-
which uses all the default parameters of the constructor, and
|
100
|
-
therefore, imputed variables are generated to augment the data and
|
101
|
-
initial-year grow factors are applied to the data. There are
|
102
|
-
situations in which you need to specify the values of the Record
|
103
|
-
constructor's arguments, but be sure you know exactly what you are
|
104
|
-
doing when attempting this.
|
105
|
-
|
106
95
|
Use Records.cps_constructor() to get a Records object instantiated
|
107
96
|
with CPS input data developed in the taxdata repository.
|
108
97
|
|
98
|
+
Use Records.puf_constructor() to get a Records object instantiated
|
99
|
+
with PUF input data developed in the taxdata repository.
|
100
|
+
|
109
101
|
Use Records.tmd_constructor() to get a Records object instantiated
|
110
102
|
with TMD input data developed in the tax-microdata repository.
|
111
103
|
"""
|
@@ -120,20 +112,16 @@ class Records(Data):
|
|
120
112
|
CPSCSV_YEAR = 2014
|
121
113
|
TMDCSV_YEAR = 2021
|
122
114
|
|
123
|
-
PUF_WEIGHTS_FILENAME = 'puf_weights.csv.gz'
|
124
|
-
PUF_RATIOS_FILENAME = 'puf_ratios.csv'
|
125
|
-
CPS_WEIGHTS_FILENAME = 'cps_weights.csv.gz'
|
126
|
-
CPS_RATIOS_FILENAME = None
|
127
115
|
CODE_PATH = os.path.abspath(os.path.dirname(__file__))
|
128
116
|
VARINFO_FILE_NAME = 'records_variables.json'
|
129
117
|
VARINFO_FILE_PATH = CODE_PATH
|
130
118
|
|
131
119
|
def __init__(self,
|
132
|
-
data=
|
133
|
-
start_year=
|
134
|
-
gfactors=
|
135
|
-
weights=
|
136
|
-
adjust_ratios=
|
120
|
+
data=None,
|
121
|
+
start_year=None,
|
122
|
+
gfactors=None,
|
123
|
+
weights=None,
|
124
|
+
adjust_ratios=None,
|
137
125
|
exact_calculations=False,
|
138
126
|
weights_scale=0.01):
|
139
127
|
# pylint: disable=too-many-positional-arguments
|
@@ -205,32 +193,58 @@ class Records(Data):
|
|
205
193
|
raise ValueError('not all PT_SSTB_income values are 0 or 1')
|
206
194
|
|
207
195
|
@staticmethod
|
208
|
-
def cps_constructor(
|
209
|
-
|
210
|
-
|
196
|
+
def cps_constructor(
|
197
|
+
data=None,
|
198
|
+
gfactors=GrowFactors(),
|
199
|
+
exact_calculations=False
|
200
|
+
):
|
211
201
|
"""
|
212
202
|
Static method returns a Records object instantiated with CPS
|
213
|
-
input data. This
|
214
|
-
|
215
|
-
This is a convenience method that eliminates the need to
|
216
|
-
specify all the details of the CPS input data just as the
|
217
|
-
default values of the arguments of the Records class constructor
|
218
|
-
eliminate the need to specify all the details of the PUF input
|
219
|
-
data.
|
203
|
+
input data. This is a convenience method that eliminates the
|
204
|
+
need to specify all the details of the CPS input data.
|
220
205
|
"""
|
221
206
|
if data is None:
|
222
207
|
data = os.path.join(Records.CODE_PATH, 'cps.csv.gz')
|
223
208
|
if gfactors is None:
|
224
209
|
weights = None
|
225
210
|
else:
|
226
|
-
weights = os.path.join(Records.CODE_PATH,
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
211
|
+
weights = os.path.join(Records.CODE_PATH, 'cps_weights.csv.gz')
|
212
|
+
return Records(
|
213
|
+
data=data,
|
214
|
+
start_year=Records.CPSCSV_YEAR,
|
215
|
+
gfactors=gfactors,
|
216
|
+
weights=weights,
|
217
|
+
adjust_ratios=None,
|
218
|
+
exact_calculations=exact_calculations,
|
219
|
+
weights_scale=0.01,
|
220
|
+
)
|
221
|
+
|
222
|
+
@staticmethod
|
223
|
+
def puf_constructor(
|
224
|
+
data='puf.csv',
|
225
|
+
gfactors=GrowFactors(),
|
226
|
+
weights='puf_weights.csv.gz',
|
227
|
+
ratios='puf_ratios.csv',
|
228
|
+
exact_calculations=False
|
229
|
+
): # pragma: no cover
|
230
|
+
"""
|
231
|
+
Static method returns a Records object instantiated with PUF
|
232
|
+
input data. This is a convenience method that eliminates the
|
233
|
+
need to specify all the details of the PUF input data.
|
234
|
+
"""
|
235
|
+
assert isinstance(data, str)
|
236
|
+
assert isinstance(gfactors, GrowFactors)
|
237
|
+
assert isinstance(weights, str)
|
238
|
+
assert isinstance(ratios, str)
|
239
|
+
return Records(
|
240
|
+
data=pd.read_csv(data),
|
241
|
+
start_year=Records.PUFCSV_YEAR,
|
242
|
+
gfactors=gfactors,
|
243
|
+
weights=pd.read_csv(weights),
|
244
|
+
adjust_ratios=pd.read_csv(ratios, index_col=0).transpose(),
|
245
|
+
exact_calculations=exact_calculations,
|
246
|
+
weights_scale=0.01,
|
247
|
+
)
|
234
248
|
|
235
249
|
@staticmethod
|
236
250
|
def tmd_constructor(
|
@@ -241,13 +255,8 @@ class Records(Data):
|
|
241
255
|
): # pragma: no cover
|
242
256
|
"""
|
243
257
|
Static method returns a Records object instantiated with TMD
|
244
|
-
input data. This
|
245
|
-
|
246
|
-
This is a convenience method that eliminates the need to
|
247
|
-
specify all the details of the TMD input data just as the
|
248
|
-
default values of the arguments of the Records class constructor
|
249
|
-
eliminate the need to specify all the details of the PUF input
|
250
|
-
data.
|
258
|
+
input data. This is a convenience method that eliminates the
|
259
|
+
need to specify all the details of the TMD input data.
|
251
260
|
"""
|
252
261
|
assert isinstance(data_path, Path)
|
253
262
|
assert isinstance(weights_path, Path)
|
@@ -395,42 +404,29 @@ class Records(Data):
|
|
395
404
|
|
396
405
|
def _adjust(self, year):
|
397
406
|
"""
|
398
|
-
Adjust value of income variables to match SOI distributions
|
407
|
+
Adjust value of PUF income variables to match SOI distributions
|
399
408
|
Note: adjustment must leave variables as numpy.ndarray type
|
400
409
|
"""
|
401
410
|
# pylint: disable=no-member
|
402
|
-
if self.ADJ.size > 0:
|
411
|
+
if self.ADJ.size > 0: # pragma: no cover
|
403
412
|
# Interest income
|
404
413
|
self.e00300 *= self.ADJ[f'INT{year}'].iloc[self.agi_bin].values
|
405
414
|
|
406
415
|
def _read_ratios(self, ratios):
|
407
416
|
"""
|
408
|
-
Read Records adjustment ratios
|
409
|
-
|
410
|
-
create empty DataFrame if None
|
417
|
+
Read Records PUF-related adjustment ratios using
|
418
|
+
specified transposed/no-index DataFrame as ratios or
|
419
|
+
create empty DataFrame if ratios is None.
|
411
420
|
"""
|
421
|
+
assert ratios is None or isinstance(ratios, pd.DataFrame)
|
412
422
|
if ratios is None:
|
413
423
|
setattr(self, 'ADJ', pd.DataFrame({'nothing': []}))
|
414
424
|
return
|
415
|
-
if isinstance(ratios, pd.DataFrame):
|
425
|
+
if isinstance(ratios, pd.DataFrame): # pragma: no cover
|
416
426
|
assert 'INT2013' in ratios.columns # check for transposed
|
417
427
|
assert ratios.index.name is None # check for no-index
|
418
428
|
ADJ = ratios
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
index_col=0)
|
424
|
-
else: # find file in conda package
|
425
|
-
ADJ = read_egg_csv(os.path.basename(ratios_path),
|
426
|
-
index_col=0) # pragma: no cover
|
427
|
-
ADJ = ADJ.transpose()
|
428
|
-
else:
|
429
|
-
msg = 'ratios is neither None nor a Pandas DataFrame nor a string'
|
430
|
-
raise ValueError(msg)
|
431
|
-
assert isinstance(ADJ, pd.DataFrame)
|
432
|
-
if ADJ.index.name != 'agi_bin':
|
433
|
-
ADJ.index.name = 'agi_bin'
|
434
|
-
self.ADJ = pd.DataFrame()
|
435
|
-
setattr(self, 'ADJ', ADJ.astype(np.float32))
|
436
|
-
del ADJ
|
429
|
+
self.ADJ = pd.DataFrame()
|
430
|
+
if ADJ.index.name != 'agi_bin':
|
431
|
+
ADJ.index.name = 'agi_bin'
|
432
|
+
setattr(self, 'ADJ', ADJ.astype(np.float32))
|