taxcalc 5.3.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.
taxcalc/taxcalcio.py CHANGED
@@ -9,6 +9,7 @@ import os
9
9
  import gc
10
10
  import copy
11
11
  import sqlite3
12
+ from pathlib import Path
12
13
  import numpy as np
13
14
  import pandas as pd
14
15
  import paramtools
@@ -75,11 +76,9 @@ class TaxCalcIO():
75
76
  self.errmsg = ''
76
77
  # check name and existence of INPUT file
77
78
  inp = 'x'
78
- self.puf_input_data = False
79
79
  self.cps_input_data = False
80
+ self.puf_input_data = False
80
81
  self.tmd_input_data = False
81
- self.tmd_weights = None
82
- self.tmd_gfactor = None
83
82
  if isinstance(input_data, str):
84
83
  # remove any leading directory path from INPUT filename
85
84
  fname = os.path.basename(input_data)
@@ -90,12 +89,23 @@ class TaxCalcIO():
90
89
  msg = 'INPUT file name does not end in .csv'
91
90
  self.errmsg += f'ERROR: {msg}\n'
92
91
  # check existence of INPUT file
93
- self.puf_input_data = input_data.endswith('puf.csv')
94
92
  self.cps_input_data = input_data.endswith('cps.csv')
93
+ self.puf_input_data = input_data.endswith('puf.csv')
95
94
  self.tmd_input_data = input_data.endswith('tmd.csv')
96
95
  if not self.cps_input_data and not os.path.isfile(input_data):
97
96
  msg = 'INPUT file could not be found'
98
97
  self.errmsg += f'ERROR: {msg}\n'
98
+ # if puf_input_data is True, construct weights and ratios paths
99
+ if self.puf_input_data: # pragma: no cover
100
+ puf_dir = os.path.dirname(input_data)
101
+ self.puf_weights = os.path.join(puf_dir, 'puf_weights.csv.gz')
102
+ self.puf_ratios = os.path.join(puf_dir, 'puf_ratios.csv')
103
+ if not os.path.isfile(self.puf_weights):
104
+ msg = f'weights file {self.puf_weights} could not be found'
105
+ self.errmsg += f'ERROR: {msg}\n'
106
+ if not os.path.isfile(self.puf_ratios):
107
+ msg = f'gfactor file {self.puf_ratios} could not be found'
108
+ self.errmsg += f'ERROR: {msg}\n'
99
109
  # if tmd_input_data is True, construct weights and gfactor paths
100
110
  if self.tmd_input_data: # pragma: no cover
101
111
  tmd_dir = os.path.dirname(input_data)
@@ -253,7 +263,7 @@ class TaxCalcIO():
253
263
  delete_file(self.output_filename.replace('.xxx', ext))
254
264
 
255
265
  def init(self, input_data, tax_year, baseline, reform, assump,
256
- aging_input_data, exact_calculations):
266
+ exact_calculations):
257
267
  """
258
268
  TaxCalcIO class post-constructor method that completes initialization.
259
269
 
@@ -262,10 +272,6 @@ class TaxCalcIO():
262
272
  First five are same as the first five of the TaxCalcIO constructor:
263
273
  input_data, tax_year, baseline, reform, assump.
264
274
 
265
- aging_input_data: boolean
266
- whether or not to extrapolate Records data from data year to
267
- tax_year.
268
-
269
275
  exact_calculations: boolean
270
276
  specifies whether or not exact tax calculations are done without
271
277
  any smoothing of "stair-step" provisions in the tax law.
@@ -406,48 +412,46 @@ class TaxCalcIO():
406
412
  pol_ref.set_year(tax_year)
407
413
  pol_bas.set_year(tax_year)
408
414
  # read input file contents into Records objects
409
- if aging_input_data:
410
- if self.cps_input_data:
411
- recs_ref = Records.cps_constructor(
412
- gfactors=gfactors_ref,
413
- exact_calculations=exact_calculations,
414
- )
415
- recs_bas = Records.cps_constructor(
416
- gfactors=gfactors_bas,
417
- exact_calculations=exact_calculations,
418
- )
419
- elif self.tmd_input_data: # pragma: no cover
420
- wghts = pd.read_csv(self.tmd_weights)
421
- recs_ref = Records(
422
- data=pd.read_csv(input_data),
423
- start_year=Records.TMDCSV_YEAR,
424
- weights=wghts,
425
- gfactors=gfactors_ref,
426
- adjust_ratios=None,
427
- exact_calculations=exact_calculations,
428
- weights_scale=1.0,
429
- )
430
- recs_bas = Records(
431
- data=pd.read_csv(input_data),
432
- start_year=Records.TMDCSV_YEAR,
433
- weights=wghts,
434
- gfactors=gfactors_bas,
435
- adjust_ratios=None,
436
- exact_calculations=exact_calculations,
437
- weights_scale=1.0,
438
- )
439
- else: # if not {cps|tmd}_input_data but aging_input_data: puf
440
- recs_ref = Records(
441
- data=input_data,
442
- gfactors=gfactors_ref,
443
- exact_calculations=exact_calculations
444
- )
445
- recs_bas = Records(
446
- data=input_data,
447
- gfactors=gfactors_bas,
448
- exact_calculations=exact_calculations
449
- )
415
+ aging_input_data = True
416
+ if self.cps_input_data:
417
+ recs_ref = Records.cps_constructor(
418
+ gfactors=gfactors_ref,
419
+ exact_calculations=exact_calculations,
420
+ )
421
+ recs_bas = Records.cps_constructor(
422
+ gfactors=gfactors_bas,
423
+ exact_calculations=exact_calculations,
424
+ )
425
+ elif self.puf_input_data: # pragma: no cover
426
+ recs_ref = Records.puf_constructor(
427
+ data=input_data,
428
+ gfactors=gfactors_ref,
429
+ weights=self.puf_weights,
430
+ ratios=self.puf_ratios,
431
+ exact_calculations=exact_calculations,
432
+ )
433
+ recs_bas = Records.puf_constructor(
434
+ data=input_data,
435
+ gfactors=gfactors_bas,
436
+ weights=self.puf_weights,
437
+ ratios=self.puf_ratios,
438
+ exact_calculations=exact_calculations,
439
+ )
440
+ elif self.tmd_input_data: # pragma: no cover
441
+ recs_ref = Records.tmd_constructor(
442
+ data_path=Path(input_data),
443
+ weights_path=Path(self.tmd_weights),
444
+ growfactors=gfactors_ref,
445
+ exact_calculations=exact_calculations,
446
+ )
447
+ recs_bas = Records.tmd_constructor(
448
+ data_path=Path(input_data),
449
+ weights_path=Path(self.tmd_weights),
450
+ growfactors=gfactors_bas,
451
+ exact_calculations=exact_calculations,
452
+ )
450
453
  else: # input_data are raw data that are not being aged
454
+ aging_input_data = False
451
455
  recs_ref = Records(
452
456
  data=input_data,
453
457
  start_year=tax_year,
@@ -486,7 +490,7 @@ class TaxCalcIO():
486
490
  dirpath = os.path.abspath(os.path.dirname(__file__))
487
491
  return os.path.join(dirpath, self.output_filename)
488
492
 
489
- def advance_to_year(self, year, aging_data):
493
+ def advance_to_year(self, year):
490
494
  """
491
495
  Update self.output_filename and advance Calculator objects to year.
492
496
  """
@@ -503,6 +507,11 @@ class TaxCalcIO():
503
507
  # advance baseline and reform Calculator objects to specified year
504
508
  self.calc_bas.advance_to_year(year)
505
509
  self.calc_ref.advance_to_year(year)
510
+ aging_data = (
511
+ self.cps_input_data or
512
+ self.puf_input_data or
513
+ self.tmd_input_data
514
+ )
506
515
  idata = 'Advance input data and' if aging_data else 'Advance'
507
516
  if not self.silent:
508
517
  print(f'{idata} policy to {year}')
taxcalc/tests/conftest.py CHANGED
@@ -27,42 +27,47 @@ def tests_path_fixture():
27
27
  return os.path.abspath(os.path.dirname(__file__))
28
28
 
29
29
 
30
- @pytest.fixture(scope='session', name='cps_path')
31
- def cps_path_fixture(tests_path):
30
+ @pytest.fixture(scope='session', name='cps_data_path')
31
+ def cps_data_path_fixture(tests_path):
32
32
  """Fixture docstring"""
33
33
  return os.path.join(tests_path, '..', 'cps.csv.gz')
34
34
 
35
35
 
36
36
  @pytest.fixture(scope='session', name='cps_fullsample')
37
- def cps_fullsample_fixture(cps_path):
37
+ def cps_fullsample_fixture(cps_data_path):
38
38
  """Fixture docstring"""
39
- return pandas.read_csv(cps_path)
39
+ return pandas.read_csv(cps_data_path)
40
40
 
41
41
 
42
42
  @pytest.fixture(scope='session')
43
43
  def cps_subsample(cps_fullsample):
44
44
  """Fixture docstring"""
45
- # draw smaller cps.csv subsample than in test_cpscsv.py
45
+ # draw a small cps.csv subsample
46
46
  return cps_fullsample.sample(frac=0.01, random_state=123456789)
47
47
 
48
48
 
49
- @pytest.fixture(scope='session', name='puf_path')
50
- def puf_path_fixture(tests_path):
49
+ @pytest.fixture(scope='session', name='puf_data_path')
50
+ def puf_data_path_fixture(tests_path):
51
51
  """Fixture docstring"""
52
52
  return os.path.join(tests_path, '..', '..', 'puf.csv')
53
53
 
54
54
 
55
- @pytest.fixture(scope='session', name='puf_fullsample')
56
- def puf_fullsample_fixture(puf_path):
55
+ @pytest.fixture(scope='session', name='puf_weights_path')
56
+ def puf_weights_path_fixture(tests_path):
57
57
  """Fixture docstring"""
58
- return pandas.read_csv(puf_path)
58
+ return os.path.join(tests_path, '..', '..', 'puf_weights.csv.gz')
59
59
 
60
60
 
61
- @pytest.fixture(scope='session')
62
- def puf_subsample(puf_fullsample):
61
+ @pytest.fixture(scope='session', name='puf_ratios_path')
62
+ def puf_ratios_path_fixture(tests_path):
63
+ """Fixture docstring"""
64
+ return os.path.join(tests_path, '..', '..', 'puf_ratios.csv')
65
+
66
+
67
+ @pytest.fixture(scope='session', name='tmd_data_path')
68
+ def tmd_data_path_fixture(tests_path):
63
69
  """Fixture docstring"""
64
- # draw same puf.csv subsample as in test_pufcsv.py
65
- return puf_fullsample.sample(frac=0.05, random_state=2222)
70
+ return os.path.join(tests_path, '..', '..', 'tmd.csv')
66
71
 
67
72
 
68
73
  @pytest.fixture(scope='session', name='test_reforms_init')
@@ -1,61 +1,61 @@
1
1
  rid,res1,res2,res3,res4
2
- 1,62.1,63.1,66.2,68.9
3
- 2,54.2,58.6,53.5,62.0
4
- 3,75.1,76.2,80.3,84.3
2
+ 1,61.2,61.7,65.1,70.4
3
+ 2,43.5,45.9,43.1,52.8
4
+ 3,67.7,68.3,72.1,81.1
5
5
  4,0.0,0.0,0.0,0.0
6
6
  5,0.0,0.0,0.0,0.0
7
- 6,38.4,39.2,40.0,41.0
8
- 7,9.8,9.9,10.5,11.0
9
- 8,1.9,2.0,2.1,2.2
10
- 9,4.4,4.3,4.9,5.3
11
- 10,8.2,8.6,9.1,9.5
12
- 11,2.4,2.7,2.6,2.8
13
- 12,0.1,0.1,0.1,0.1
14
- 13,-33.5,-32.1,-35.0,-36.5
15
- 14,-0.1,-0.1,-0.1,-0.1
16
- 15,0.2,0.2,0.2,0.3
17
- 16,-1.0,-1.0,-1.5,-1.6
7
+ 6,33.1,34.1,35.9,41.4
8
+ 7,6.8,7.0,7.7,10.7
9
+ 8,1.8,1.9,2.0,2.3
10
+ 9,5.6,5.7,5.6,7.6
11
+ 10,5.6,5.8,6.4,6.1
12
+ 11,0.0,0.0,0.0,0.0
13
+ 12,0.0,0.0,0.0,0.0
14
+ 13,-34.5,-33.0,-36.1,-38.0
15
+ 14,-0.1,-0.1,-0.1,-0.2
16
+ 15,0.5,0.4,0.3,0.5
17
+ 16,-0.7,-0.8,-1.1,-1.2
18
18
  17,-0.2,-0.2,-0.3,-0.3
19
- 18,35.8,37.3,40.2,42.5
20
- 19,68.2,69.9,75.1,80.2
21
- 20,103.3,106.9,116.1,122.6
22
- 21,68.7,70.7,76.4,80.6
23
- 22,9.6,11.0,10.0,10.3
24
- 23,0.3,0.3,0.3,0.4
25
- 24,52.5,54.2,57.2,60.3
26
- 25,2.0,2.1,2.2,2.3
27
- 26,0.1,0.1,0.1,0.1
28
- 27,0.2,0.2,0.2,0.2
29
- 28,4.0,3.8,4.5,4.9
30
- 29,15.2,13.8,17.9,19.4
31
- 30,-6.4,-6.2,-1.6,-1.6
32
- 31,58.2,58.6,62.5,66.3
33
- 32,12.6,12.1,14.0,15.1
34
- 33,7.6,7.1,8.4,9.1
35
- 34,-1.3,-0.9,-1.5,-1.6
36
- 35,-2.9,-2.8,-3.4,-3.5
37
- 36,3.2,3.3,3.6,3.9
38
- 37,30.9,32.0,35.4,37.3
39
- 38,9.7,10.0,11.2,11.8
40
- 39,-0.6,-0.6,-0.7,-0.7
41
- 40,56.0,53.5,52.7,51.9
42
- 41,0.6,0.6,0.7,0.7
19
+ 18,26.8,27.3,30.0,33.1
20
+ 19,78.5,79.4,87.3,96.4
21
+ 20,64.9,66.7,73.7,84.8
22
+ 21,39.6,40.8,45.0,52.8
23
+ 22,8.9,9.9,9.6,10.8
24
+ 23,0.0,0.0,0.0,0.0
25
+ 24,34.4,35.5,38.0,42.8
26
+ 25,1.5,1.5,1.6,1.8
27
+ 26,0.0,0.1,0.1,0.1
28
+ 27,0.1,0.1,0.1,0.2
29
+ 28,0.5,0.4,0.5,1.6
30
+ 29,22.4,20.9,25.3,27.0
31
+ 30,-3.2,-3.1,-0.8,-0.8
32
+ 31,53.7,54.2,57.4,66.2
33
+ 32,7.9,7.8,8.6,13.6
34
+ 33,3.9,3.8,4.3,6.8
35
+ 34,-0.5,-0.4,-0.8,-0.9
36
+ 35,-1.2,-1.1,-1.7,-1.9
37
+ 36,1.5,1.5,2.1,2.6
38
+ 37,15.8,16.2,18.9,25.1
39
+ 38,3.3,3.3,4.0,5.8
40
+ 39,-0.3,-0.2,-0.3,-0.4
41
+ 40,52.0,50.6,49.4,55.3
42
+ 41,0.4,0.4,0.5,0.6
43
43
  42,-0.2,-0.2,-0.2,-0.2
44
- 43,71.8,68.8,67.6,69.4
45
- 44,1.1,1.1,1.1,1.2
46
- 45,-2.1,-2.0,-2.1,-2.2
47
- 46,-2.0,-1.7,-2.0,-2.1
48
- 47,-0.8,-0.8,-0.8,-0.7
44
+ 43,59.1,57.4,52.5,68.5
45
+ 44,1.3,1.2,1.2,1.5
46
+ 45,-2.1,-2.0,-2.1,-2.6
47
+ 46,-2.0,-1.7,-1.9,-2.4
48
+ 47,-0.9,-0.8,-0.7,-0.9
49
49
  48,-0.0,-0.0,-0.0,-0.0
50
- 49,-27.2,-24.3,-31.9,-34.8
51
- 50,-0.4,-0.4,-0.4,-0.4
52
- 51,-187.0,-187.5,-193.6,-201.6
53
- 52,-129.1,-128.5,-131.9,-136.9
54
- 53,31.6,34.1,32.5,42.1
50
+ 49,-37.3,-36.0,-40.4,-44.7
51
+ 50,-0.1,-0.1,-0.1,-0.1
52
+ 51,-184.8,-185.3,-189.7,-206.8
53
+ 52,-129.7,-129.6,-131.1,-143.6
54
+ 53,3.5,3.9,2.9,5.6
55
55
  54,0.0,0.0,0.0,0.0
56
- 55,-68.2,-68.4,-68.7,-68.7
57
- 56,-68.8,-68.9,-69.2,-69.2
58
- 57,1.4,1.7,1.7,1.4
59
- 58,-16.8,-17.4,-23.7,-19.2
60
- 59,-12.2,-12.2,-21.2,-13.3
61
- 60,-46.9,-48.1,-49.3,-52.1
56
+ 55,-65.5,-71.9,-72.4,-72.5
57
+ 56,-66.6,-73.3,-73.8,-73.9
58
+ 57,-23.7,-25.7,-26.9,-28.5
59
+ 58,-25.5,-26.4,-33.6,-28.8
60
+ 59,-51.2,-52.9,-60.1,-52.3
61
+ 60,-51.7,-53.2,-54.4,-57.5