Source code for taxcalc.growfactors

"""
Tax-Calculator GrowFactors class.
"""
# CODING-STYLE CHECKS:
# pycodestyle growfactors.py
# pylint --disable=locally-disabled growfactors.py

import os
import numpy as np
import pandas as pd
from taxcalc.utils import read_egg_csv


[docs] class GrowFactors(): """ Constructor for the GrowFactors class. Parameters ---------- growfactors_filename: None or string string is path to the CSV file in which grow factors reside; default value of None uses file containing puf/cps grow factors. Raises ------ ValueError: if growfactors_filename is neither None or a string. if growfactors_filename string points to a non-existent file. Returns ------- class instance: GrowFactors Notes ----- Typical usage is "gfactor = GrowFactors()", which produces an object containing baseline growth factors in the GrowFactors.FILE_NAME file, which is for use with puf and cps data from the taxdata repository. """ PACKAGE_FILE_NAMES = ['growfactors.csv', 'tmd_growfactors.csv'] FILE_PATH = os.path.abspath(os.path.dirname(__file__)) VALID_NAMES = set(['ABOOK', 'ACGNS', 'ACPIM', 'ACPIU', 'ADIVS', 'AINTS', 'AIPD', 'ASCHCI', 'ASCHCL', 'ASCHEI', 'ASCHEL', 'ASCHF', 'ASOCSEC', 'ATXPY', 'AUCOMP', 'AWAGE', 'ABENOTHER', 'ABENMCARE', 'ABENMCAID', 'ABENSSI', 'ABENSNAP', 'ABENWIC', 'ABENHOUSING', 'ABENTANF', 'ABENVET']) def __init__(self, growfactors_filename=None): # read grow factors from specified growfactors_filename gfdf = pd.DataFrame() if growfactors_filename is None: # read puf/cps growfactors from package gfdf = read_egg_csv(GrowFactors.PACKAGE_FILE_NAMES[0], index_col='YEAR') # pragma: no cover elif isinstance(growfactors_filename, str): if growfactors_filename in GrowFactors.PACKAGE_FILE_NAMES: # read growfactors from package gfdf = read_egg_csv(growfactors_filename, index_col='YEAR') # pragma: no cover else: if os.path.isfile(growfactors_filename): gfdf = pd.read_csv(growfactors_filename, index_col='YEAR') else: # file does not exist msg = ( f'growfactors file {growfactors_filename} ' 'does not exist' ) raise ValueError(msg) else: raise ValueError('growfactors_filename is not a string') assert isinstance(gfdf, pd.DataFrame) # check validity of gfdf column names gfdf_names = set(list(gfdf)) if gfdf_names != GrowFactors.VALID_NAMES: msg = 'missing names are: {} and invalid names are: {}' missing = GrowFactors.VALID_NAMES - gfdf_names invalid = gfdf_names - GrowFactors.VALID_NAMES raise ValueError(msg.format(missing, invalid)) # determine first_year and last_year from gfdf self._first_year = min(gfdf.index) self._last_year = max(gfdf.index) # set gfdf as attribute of class self.gfdf = pd.DataFrame() setattr(self, 'gfdf', gfdf.astype(np.float64)) del gfdf # specify factors as being unused (that is, not yet accessed) self.used = False @property def first_year(self): """ GrowFactors class first_year property. """ return self._first_year @property def last_year(self): """ GrowFactors class last_year property. """ return self._last_year
[docs] def price_inflation_rates(self, firstyear, lastyear): """ Return list of price inflation rates rounded to four decimal digits. """ self.used = True if firstyear > lastyear: msg = 'first_year={} > last_year={}' raise ValueError(msg.format(firstyear, lastyear)) if firstyear < self.first_year: msg = 'firstyear={} < GrowFactors.first_year={}' raise ValueError(msg.format(firstyear, self.first_year)) if lastyear > self.last_year: msg = 'last_year={} > GrowFactors.last_year={}' raise ValueError(msg.format(lastyear, self.last_year)) rates = [round((self.gfdf['ACPIU'][cyr] - 1.0), 4) for cyr in range(firstyear, lastyear + 1)] return rates
[docs] def wage_growth_rates(self, firstyear, lastyear): """ Return list of wage growth rates rounded to four decimal digits. """ self.used = True if firstyear > lastyear: msg = 'firstyear={} > lastyear={}' raise ValueError(msg.format(firstyear, lastyear)) if firstyear < self.first_year: msg = 'firstyear={} < GrowFactors.first_year={}' raise ValueError(msg.format(firstyear, self.first_year)) if lastyear > self.last_year: msg = 'lastyear={} > GrowFactors.last_year={}' raise ValueError(msg.format(lastyear, self.last_year)) rates = [round((self.gfdf['AWAGE'][cyr] - 1.0), 4) for cyr in range(firstyear, lastyear + 1)] return rates
[docs] def factor_value(self, name, year): """ Return value of factor with specified name for specified year. """ self.used = True if name not in GrowFactors.VALID_NAMES: msg = 'name={} not in GrowFactors.VALID_NAMES' raise ValueError(msg.format(year, name)) if year < self.first_year: msg = 'year={} < GrowFactors.first_year={}' raise ValueError(msg.format(year, self.first_year)) if year > self.last_year: msg = 'year={} > GrowFactors.last_year={}' raise ValueError(msg.format(year, self.last_year)) return self.gfdf.loc[year, name]
[docs] def update(self, name, year, diff): """ Add to self.gfdf (for name and year) the specified diff amount. """ if self.used: msg = 'cannot update growfactors after they have been used' raise ValueError(msg) assert name in GrowFactors.VALID_NAMES if year >= self.first_year and year <= self.last_year: assert isinstance(diff, float) self.gfdf.loc[year, name] += diff