taxcalc 5.2.0__py3-none-any.whl → 6.0.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.
Files changed (46) hide show
  1. taxcalc/__init__.py +3 -3
  2. taxcalc/calcfunctions.py +2 -2
  3. taxcalc/calculator.py +4 -4
  4. taxcalc/cli/tc.py +16 -19
  5. taxcalc/data.py +2 -3
  6. taxcalc/decorators.py +9 -8
  7. taxcalc/growfactors.py +2 -1
  8. taxcalc/policy.py +6 -23
  9. taxcalc/policy_current_law.json +31 -631
  10. taxcalc/records.py +78 -82
  11. taxcalc/records_variables.json +106 -106
  12. taxcalc/reforms/ARPA.out.csv +9 -9
  13. taxcalc/taxcalcio.py +101 -77
  14. taxcalc/tests/conftest.py +20 -15
  15. taxcalc/tests/puf_var_correl_coeffs_2016.csv +24 -24
  16. taxcalc/tests/puf_var_wght_means_by_year.csv +11 -11
  17. taxcalc/tests/pufcsv_agg_expect.csv +20 -20
  18. taxcalc/tests/pufcsv_mtr_expect.txt +21 -21
  19. taxcalc/tests/reforms.json +3 -1
  20. taxcalc/tests/reforms_expect.csv +54 -54
  21. taxcalc/tests/test_4package.py +8 -9
  22. taxcalc/tests/test_calculator.py +55 -18
  23. taxcalc/tests/test_consumption.py +2 -2
  24. taxcalc/tests/test_cpscsv.py +2 -24
  25. taxcalc/tests/test_data.py +11 -3
  26. taxcalc/tests/test_decorators.py +57 -52
  27. taxcalc/tests/test_growdiff.py +2 -2
  28. taxcalc/tests/test_parameters.py +101 -53
  29. taxcalc/tests/test_policy.py +154 -154
  30. taxcalc/tests/test_records.py +144 -9
  31. taxcalc/tests/test_reforms.py +104 -104
  32. taxcalc/tests/test_taxcalcio.py +13 -62
  33. taxcalc/utils.py +3 -3
  34. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/METADATA +3 -6
  35. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/RECORD +39 -46
  36. taxcalc/puf_ratios.csv +0 -26
  37. taxcalc/puf_weights.csv.gz +0 -0
  38. taxcalc/reforms/clp.out.csv +0 -10
  39. taxcalc/tests/test_compare.py +0 -330
  40. taxcalc/tests/test_compatible_data.py +0 -334
  41. taxcalc/tests/test_puf_var_stats.py +0 -194
  42. taxcalc/tests/test_pufcsv.py +0 -328
  43. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/WHEEL +0 -0
  44. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/entry_points.txt +0 -0
  45. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/licenses/LICENSE +0 -0
  46. {taxcalc-5.2.0.dist-info → taxcalc-6.0.0.dist-info}/top_level.txt +0 -0
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 the string 'puf.csv'
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
- default value is PUFCSV_YEAR.
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: string or Pandas DataFrame or None
51
- string describes CSV file in which weights reside;
52
- DataFrame already contains weights;
53
- None creates empty sample-weights DataFrame;
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: string or Pandas DataFrame or None
59
- string describes CSV file in which adjustment ratios reside;
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 filename of the PUF adjustment ratios.
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='puf.csv',
133
- start_year=PUFCSV_YEAR,
134
- gfactors=GrowFactors(),
135
- weights=PUF_WEIGHTS_FILENAME,
136
- adjust_ratios=PUF_RATIOS_FILENAME,
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(data=None,
209
- gfactors=GrowFactors(),
210
- exact_calculations=False):
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 works in a analogous way to Records(), which
214
- returns a Records object instantiated with PUF input data.
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
- Records.CPS_WEIGHTS_FILENAME)
228
- return Records(data=data,
229
- start_year=Records.CPSCSV_YEAR,
230
- gfactors=gfactors,
231
- weights=weights,
232
- adjust_ratios=Records.CPS_RATIOS_FILENAME,
233
- exact_calculations=exact_calculations)
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 works in a analogous way to Records(), which
245
- returns a Records object instantiated with PUF input data.
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 from file or
409
- use specified transposed/no-index DataFrame as ratios or
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
- elif isinstance(ratios, str):
420
- ratios_path = os.path.join(Records.CODE_PATH, ratios)
421
- if os.path.isfile(ratios_path):
422
- ADJ = pd.read_csv(ratios_path,
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))