示例#1
0
def makeMPCfig(kappa, weights):
    '''
    Plot the CDF of the marginal propensity to consume. A sub-function of makeCSTWresults().
    
    Parameters
    ----------
    kappa : np.array
        Array of (annualized) marginal propensities to consume for the economy.
    weights : np.array
        Age-conditional weight array for the data in kappa.
        
    Returns
    -------
    these_percents : np.array
        Array of percentiles of the marginal propensity to consume.
    kappa_percentiles : np.array
        Array of MPCs corresponding to the percentiles in these_percents.
    '''
    these_percents = np.linspace(0.0001, 0.9999, 201)
    kappa_percentiles = getPercentiles(kappa,
                                       weights,
                                       percentiles=these_percents)
    plt.plot(kappa_percentiles, these_percents, '-k', linewidth=1.5)
    plt.xlabel('Marginal propensity to consume', fontsize=14)
    plt.ylabel('Cumulative probability', fontsize=14)
    plt.title('CDF of the MPC', fontsize=16)
    plt.show()
    return (these_percents, kappa_percentiles)
示例#2
0
文件: cstwMPC.py 项目: chiomh/HARK
def makeMPCfig(kappa,weights):
    '''
    Plot the CDF of the marginal propensity to consume. A sub-function of makeCSTWresults().
    
    Parameters
    ----------
    kappa : np.array
        Array of (annualized) marginal propensities to consume for the economy.
    weights : np.array
        Age-conditional weight array for the data in kappa.
        
    Returns
    -------
    these_percents : np.array
        Array of percentiles of the marginal propensity to consume.
    kappa_percentiles : np.array
        Array of MPCs corresponding to the percentiles in these_percents.
    '''
    these_percents = np.linspace(0.0001,0.9999,201)
    kappa_percentiles = getPercentiles(kappa,weights,percentiles=these_percents)
    plt.plot(kappa_percentiles,these_percents,'-k',linewidth=1.5)
    plt.xlabel('Marginal propensity to consume',fontsize=14)
    plt.ylabel('Cumulative probability',fontsize=14)
    plt.title('CDF of the MPC',fontsize=16)
    plt.show()
    return (these_percents,kappa_percentiles)
示例#3
0
def makeValidationFigures(params, use_cohorts):
    '''
    Make several figures that compare simulated outcomes from the estimated model
    to their data counterparts, for external validation.
    
    Parameters
    ----------
    params : np.array
        Size 33 array of model parameters, like that used for estimation.
    use_cohorts : bool
        Indicator for whether or not to model differences across cohorts.
        
    Returns
    -------
    None
    '''
    # Make, solve, and simulate the types
    param_dict = convertVecToDict(params)
    if use_cohorts:
        type_list = makeMultiTypeWithCohorts(param_dict)
    else:
        type_list = makeMultiTypeSimple(param_dict)
    for this_type in type_list:
        this_type.track_vars.append('MedLvlNow')
        this_type.track_vars.append('iLvlNow')
        this_type.track_vars.append('HitCfloor')
        this_type.CalcExpectationFuncs = True
        this_type.DeleteSolution = False
    multiThreadCommandsFake(type_list, ['estimationAction()'], num_jobs=5)

    # Combine simulated data across all types
    aLvlHist = np.concatenate(
        [this_type.aLvlNow_hist for this_type in type_list], axis=1)
    hLvlHist = np.concatenate(
        [this_type.hLvlNow_hist for this_type in type_list], axis=1)
    OOPhist = np.concatenate(
        [this_type.OOPmedNow_hist for this_type in type_list], axis=1)
    MortHist = np.concatenate(
        [this_type.DiePrbNow_hist for this_type in type_list], axis=1)
    WeightHist = np.concatenate(
        [this_type.CumLivPrb_hist for this_type in type_list], axis=1)
    MedHist = np.concatenate(
        [this_type.MedLvlNow_hist for this_type in type_list], axis=1)

    # Combine data labels across types
    HealthTert = np.concatenate(
        [this_type.HealthTert for this_type in type_list])
    HealthQuint = np.concatenate(
        [this_type.HealthQuint for this_type in type_list])
    WealthQuint = np.concatenate(
        [this_type.WealthQuint for this_type in type_list])
    IncQuint = np.concatenate(
        [this_type.IncQuintLong for this_type in type_list])
    Sex = np.concatenate([this_type.SexLong for this_type in type_list])

    # Combine in-data-span masking array across all types
    Active = hLvlHist > 0.
    InDataSpan = np.concatenate(
        [this_type.InDataSpanArray for this_type in type_list], axis=1)
    WeightAdj = InDataSpan * WeightHist

    # For each type, calculate the probability that no health investment is purchased at each age
    # and the probability the
    iLvlZeroRate = np.zeros((10, 25))
    HitCfloorRate = np.zeros((10, 25))
    for j in range(10):
        this_type = type_list[j]
        iLvlZero = this_type.iLvlNow_hist == 0.
        HitCfloor = this_type.HitCfloor_hist == 1.
        iLvlZeroSum = np.sum(iLvlZero * this_type.CumLivPrb_hist, axis=1)
        HitCfloorSum = np.sum(HitCfloor * this_type.CumLivPrb_hist, axis=1)
        PopSum = np.sum(this_type.CumLivPrb_hist, axis=1)
        iLvlZeroRate[j, :] = iLvlZeroSum / PopSum
        HitCfloorRate[j, :] = HitCfloorSum / PopSum

    # Calculate median (pseudo) bank balances for each type
    bLvl_init_median = np.zeros(10)
    for n in range(10):
        bLvl_init_median[n] = np.median(
            type_list[n].aLvlInit) + type_list[n].IncomeNow[2]

    # Extract deciles of health by age from the simulated data
    pctiles = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
    SimHealthPctiles = np.zeros((15, len(pctiles)))
    for t in range(15):
        SimHealthPctiles[t, :] = getPercentiles(hLvlHist[t, :],
                                                weights=WeightAdj[t, :],
                                                percentiles=pctiles)

    # Plot the probability of purchasing zero health investment by age, sex, and income
    colors = ['b', 'r', 'g', 'c', 'm']
    AgeVec = np.linspace(67., 95., num=15)
    for n in range(5):
        plt.plot(AgeVec, iLvlZeroRate[n, :15], '-' + colors[n])
    plt.xlabel('Age')
    plt.ylabel(r'Prob[$n_{it}=0$]')
    plt.title('Probability of Buying No Health Investment, Women')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ])
    plt.savefig('../Figures/ZeroInvstWomen.pdf')
    plt.show()
    for n in range(5):
        plt.plot(AgeVec, iLvlZeroRate[n + 5, :15], '-' + colors[n])
    plt.xlabel('Age')
    plt.ylabel(r'Prob[$n_{it}=0$]')
    plt.title('Probability of Buying No Health Investment, Men')
    plt.savefig('../Figures/ZeroInvstMen.pdf')
    plt.show()

    # Plot the probability of hitting the consumption floor by age, sex, and income
    colors = ['b', 'r', 'g', 'c', 'm']
    AgeVec = np.linspace(67., 95., num=15)
    for n in range(5):
        plt.plot(AgeVec, HitCfloorRate[n, :15], '-' + colors[n])
    plt.xlabel('Age')
    plt.ylabel(r'Prob[$c_{it}={c}$]')
    plt.title('Probability of Using Consumption Floor, Women')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ])
    plt.savefig('../Figures/cFloorWomen.pdf')
    plt.show()
    for n in range(5):
        plt.plot(AgeVec, HitCfloorRate[n + 5, :15], '-' + colors[n])
    plt.xlabel('Age')
    plt.ylabel(r'Prob[$c_{it}={c}$]')
    plt.title('Probability of Using Consumption Floor, Men')
    plt.savefig('../Figures/cFloorMen.pdf')
    plt.show()

    # Plot health investment as a function of market resources by type, holding h and Dev fixed
    B = np.linspace(1., 50., 201)
    some_ones = np.ones_like(B)
    hLvl = 0.6
    Dev = 0.0
    t = 0
    Age = str(65 + 2 * t)
    for i in range(5):
        this_type = type_list[i]
        MedShk = np.exp(this_type.MedShkMeanFunc[t](hLvl) +
                        Dev * this_type.MedShkStdFunc(hLvl))
        I = np.maximum(
            this_type.solution[t].PolicyFunc.iFunc(B, hLvl * some_ones,
                                                   MedShk * some_ones), 0.0)
        plt.plot(B, I, '-' + colors[i])
    plt.xlabel(r'Bank balances $b_{it}$, \$10,000 (y2000)')
    plt.ylabel(r'Health investment $n_{it}$, \$10,000 (y2000)')
    plt.xlim([1., 50.])
    plt.ylim([-0.01, 0.65])
    #plt.legend(['Bottom quintile','Second quintile','Third quintile','Fourth quintile','Top quintile'])
    plt.title('Health Investment Function at Age ' + Age + ' by Income, Women')
    plt.savefig('../Figures/iFuncWomen.pdf')
    plt.show()
    for i in range(5):
        this_type = type_list[i + 5]
        MedShk = np.exp(this_type.MedShkMeanFunc[t](hLvl) +
                        Dev * this_type.MedShkStdFunc(hLvl))
        I = np.maximum(
            this_type.solution[t].PolicyFunc.iFunc(B, hLvl * some_ones,
                                                   MedShk * some_ones), 0.0)
        plt.plot(B, I, '-' + colors[i])
    plt.xlabel(r'Bank balances $b_{it}$, \$10,000 (y2000)')
    plt.ylabel(r'Health investment $n_{it}$, \$10,000 (y2000)')
    plt.xlim([1., 50.])
    plt.ylim([-0.01, 0.65])
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ],
               loc=4)
    plt.title('Health Investment Function at Age ' + Age + ' by Income, Men')
    plt.savefig('../Figures/iFuncMen.pdf')
    plt.show()

    # Plot PDV of total medical expenses by health at median wealth at age 69-70 by income quintile and sex
    t = 2
    H = np.linspace(0.0, 1.0, 201)
    for n in range(5):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].TotalMedPDVfunc(B, H)
        plt.plot(H, M, color=colors[n])
    plt.xlim([0., 1.])
    plt.ylim([0., 17])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('PDV total medical care, $10,000 (y2000)')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ])
    plt.title('Total Medical Expenses by Health and Income, Women')
    plt.savefig('../Figures/TotalMedPDVbyIncomeWomen.pdf')
    plt.show()
    for n in range(5, 10):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].TotalMedPDVfunc(B, H)
        plt.plot(H, M, color=colors[n - 5])
    plt.xlim([0., 1.])
    plt.ylim([0., 17])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('PDV total medical care, $10,000 (y2000)')
    #plt.legend(['Bottom quintile','Second quintile','Third quintile','Fourth quintile','Top quintile'])
    plt.title('Total Medical Expenses by Health and Income, Men')
    plt.savefig('../Figures/TotalMedPDVbyIncomeMen.pdf')
    plt.show()

    # Plot PDV of OOP medical expenses by health at median wealth at age 69-70 by income quintile and sex
    colors = ['b', 'r', 'g', 'c', 'm']
    t = 2
    H = np.linspace(0.0, 1.0, 201)
    for n in range(5):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].OOPmedPDVfunc(B, H)
        plt.plot(H, M, color=colors[n])
    plt.xlim([0., 1.])
    plt.ylim([0., 3.5])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('PDV OOP medical expenses, $10,000 (y2000)')
    #plt.legend(['Bottom quintile','Second quintile','Third quintile','Fourth quintile','Top quintile'])
    plt.title('OOP Medical Expenses by Health and Income, Women')
    plt.savefig('../Figures/OOPmedPDVbyIncomeWomen.pdf')
    plt.show()
    for n in range(5, 10):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].OOPmedPDVfunc(B, H)
        plt.plot(H, M, color=colors[n - 5])
    plt.xlim([0., 1.])
    plt.ylim([0., 3.5])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('PDV total medical care, $10,000 (y2000)')
    #plt.legend(['Bottom quintile','Second quintile','Third quintile','Fourth quintile','Top quintile'])
    plt.title('OOP Medical Expenses by Health and Income, Men')
    plt.savefig('../Figures/OOPmedPDVbyIncomeMen.pdf')
    plt.show()

    # Plot life expectancy by health at median wealth at age 69-70 by income quintile and sex
    colors = ['b', 'r', 'g', 'c', 'm']
    t = 2
    H = np.linspace(0.0, 1.0, 201)
    for n in range(5):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].ExpectedLifeFunc(B, H)
        plt.plot(H, M, color=colors[n])
    plt.xlim([0., 1.])
    plt.ylim([0., 20.])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('Remaining years of life expectancy')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ])
    plt.title('Life Expectancy at Age 69 by Health and Income, Women')
    plt.savefig('../Figures/LifeExpectancybyIncomeWomen.pdf')
    plt.show()
    for n in range(5, 10):
        B = bLvl_init_median[n] * np.ones_like(H)
        M = type_list[n].solution[t].ExpectedLifeFunc(B, H)
        plt.plot(H, M, color=colors[n - 5])
    plt.xlim([0., 1.])
    plt.ylim([0., 20.])
    plt.xlabel(r'Health capital $h_{it}$')
    plt.ylabel('Remaining years of life expectancy')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ])
    plt.title('Life Expectancy at Age 69 by Health and Income, Men')
    plt.savefig('../Figures/LifeExpectancybyIncomeMen.pdf')
    plt.show()

    # Extract deciles of health from the HRS data
    DataHealthPctiles = np.zeros((15, len(pctiles)))
    for t in range(15):
        these = np.logical_and(Data.AgeBoolArray[:, :, t], Data.Alive)
        h_temp = Data.h_data[these]
        DataHealthPctiles[t, :] = getPercentiles(h_temp, percentiles=pctiles)

    # Plot deciles of health by by age
    plt.plot(AgeVec, SimHealthPctiles, '-k')
    plt.plot(AgeVec, DataHealthPctiles, '--k')
    plt.ylim(0., 1.)
    plt.ylabel('Health capital $h_{it}$')
    plt.xlabel('Age')
    plt.title('Simulated vs Actual Distribution of Health by Age')
    plt.savefig('../Figures/HealthDistribution.pdf')
    plt.show()

    OOPmodFunc = lambda x: np.log(10000 * x)

    # Extract many percentiles of OOP spending from the simulated data
    OOP_sim = OOPhist.flatten()
    Weight_temp = WeightAdj.flatten()
    CDFvalsSim = np.linspace(0.0001, 0.999, 1000)
    OOPsimCDF_A0 = getPercentiles(OOP_sim * 10000,
                                  weights=Weight_temp,
                                  percentiles=CDFvalsSim)
    OOPsimCDF_B0 = getPercentiles(OOPmodFunc(OOP_sim),
                                  weights=Weight_temp,
                                  percentiles=CDFvalsSim)

    # Extract some percentiles of OOP spending from the HRS data
    these = np.logical_and(Data.Alive, np.logical_not(np.isnan(Data.m_data)))
    OOP_data = Data.m_data[these]
    CDFvalsData = np.linspace(0.0001, 0.999, 500)
    OOPdataCDF_A0 = getPercentiles(OOP_data * 10000,
                                   weights=None,
                                   percentiles=CDFvalsData)
    OOPdataCDF_B0 = getPercentiles(OOPmodFunc(OOP_data),
                                   weights=None,
                                   percentiles=CDFvalsData)

    # Plot the CDF of log out-of-pocket medical spending
    plt.subplot(211)
    plt.title('CDF of OOP Medical Spending')
    plt.plot(OOPdataCDF_B0, CDFvalsData, '-r')
    plt.plot(OOPsimCDF_B0, CDFvalsSim, '-b')
    plt.xlim(8., 11.5)
    plt.ylim(0.85, 1.0)
    plt.xticks([
        np.log(3000),
        np.log(6000),
        np.log(12000),
        np.log(24000),
        np.log(48000),
        np.log(96000)
    ], ['3000', '6000', '12000', '24000', '48000', '96000'])

    # Plot the CDF of out-of-pocket medical spending
    plt.subplot(212)
    plt.plot(OOPdataCDF_A0, CDFvalsData, '-r')
    plt.plot(OOPsimCDF_A0, CDFvalsSim, '-b')
    plt.xlim(0., 3000.)
    plt.ylim(0.0, 0.9)
    plt.xlabel('Out-of-pocket medical expenses, biannual')
    plt.ylabel('Cumulative distribution')
    plt.legend(['HRS data', 'Model'], loc=4)
    plt.savefig('../Figures/OOPdistribution.pdf')
    plt.show()

    # Calculate the serial correlation of log OOP medical spending in simulated data
    Med_sim = np.log(10000 * OOPhist + 1.)
    serial_corr_sim = np.zeros(15)
    serial_corr_sim_inc = np.zeros((15, 5))
    for t in range(15):
        these = np.logical_and(WeightAdj[t + 1, :] > 0., WeightAdj[t + 1, :] <
                               1.)  # Alive but not the first simulated period
        Med_t = Med_sim[t + 1, these]
        Med_tm1 = Med_sim[t, these]
        weight_reg = WeightAdj[t + 1, these]
        const_reg = np.ones_like(Med_t)
        regressors = np.transpose(np.vstack([const_reg, Med_tm1]))
        temp_model = WLS(Med_t, regressors, weights=weight_reg)
        temp_results = temp_model.fit()
        serial_corr_sim[t] = temp_results.rsquared
        for i in range(5):
            those = np.logical_and(these, IncQuint == i + 1)
            Med_t = Med_sim[t + 1, those]
            Med_tm1 = Med_sim[t, those]
            weight_reg = WeightAdj[t + 1, those]
            const_reg = np.ones_like(Med_t)
            regressors = np.transpose(np.vstack([const_reg, Med_tm1]))
            temp_model = WLS(Med_t, regressors, weights=weight_reg)
            temp_results = temp_model.fit()
            serial_corr_sim_inc[t, i] = temp_results.rsquared

    # Calculate the serial correlation of log OOP medical spending in HRS data
    DataExists = np.logical_and(np.logical_not(np.isnan(Data.m_data[:-1, :])),
                                np.logical_not(np.isnan(Data.m_data[1:, :])))
    BothAlive = np.logical_and(Data.Alive[:-1, :], Data.Alive[1:, :])
    Usable = np.logical_and(DataExists, BothAlive)
    serial_corr_data = np.zeros(15)
    serial_corr_data_inc = np.zeros((15, 5))
    Med_data = np.log(10000 * Data.m_data + 1.)
    for t in range(15):
        these = np.logical_and(Usable, Data.AgeBoolArray[:-1, :, t])
        Med_t = Med_data[1:, :][these]
        Med_tm1 = Med_data[:-1, :][these]
        const_reg = np.ones_like(Med_t)
        regressors = np.transpose(np.vstack([const_reg, Med_tm1]))
        temp_model = OLS(Med_t, regressors)
        temp_results = temp_model.fit()
        serial_corr_data[t] = temp_results.rsquared
        for i in range(5):
            those = np.logical_and(these, Data.IncQuintBoolArray[:-1, :, i])
            Med_t = Med_data[1:, :][those]
            Med_tm1 = Med_data[:-1, :][those]
            const_reg = np.ones_like(Med_t)
            regressors = np.transpose(np.vstack([const_reg, Med_tm1]))
            temp_model = OLS(Med_t, regressors)
            temp_results = temp_model.fit()
            serial_corr_data_inc[t, i] = temp_results.rsquared

    # Make a plot of serial correlation of OOP medical expenses
    plt.subplot(3, 2, 1)
    plt.plot(AgeVec, serial_corr_data, '-r')
    plt.plot(AgeVec, serial_corr_sim, '-b')
    plt.ylim(0, 0.5)
    plt.xticks([])
    plt.text(75, 0.4, 'All individuals')

    plt.subplot(3, 2, 2)
    plt.plot(AgeVec, serial_corr_data_inc[:, 0], '-r')
    plt.plot(AgeVec, serial_corr_sim_inc[:, 0], '-b')
    plt.ylim(0, 0.5)
    plt.xticks([])
    plt.yticks([])
    plt.text(70, 0.4, 'Bottom income quintile')

    plt.subplot(3, 2, 3)
    plt.plot(AgeVec, serial_corr_data_inc[:, 1], '-r')
    plt.plot(AgeVec, serial_corr_sim_inc[:, 1], '-b')
    plt.ylim(0, 0.5)
    plt.xticks([])
    plt.text(67, 0.4, 'Second income quintile')
    plt.ylabel('$R^2$ of regression of $\log(OOP_{t})$ on $\log(OOP_{t-1})$')

    plt.subplot(3, 2, 4)
    plt.plot(AgeVec, serial_corr_data_inc[:, 2], '-r')
    plt.plot(AgeVec, serial_corr_sim_inc[:, 2], '-b')
    plt.ylim(0, 0.5)
    plt.xticks([])
    plt.yticks([])
    plt.text(70, 0.4, 'Third income quintile')

    plt.subplot(3, 2, 5)
    plt.plot(AgeVec, serial_corr_data_inc[:, 3], '-r')
    plt.plot(AgeVec, serial_corr_sim_inc[:, 3], '-b')
    plt.ylim(0, 0.5)
    plt.xlabel('Age')
    plt.text(70, 0.4, 'Fourth income quintile')

    plt.subplot(3, 2, 6)
    plt.plot(AgeVec, serial_corr_data_inc[:, 4], '-r')
    plt.plot(AgeVec, serial_corr_sim_inc[:, 4], '-b')
    plt.ylim(0, 0.5)
    plt.xlabel('Age')
    plt.yticks([])
    plt.text(70, 0.4, 'Top income quintile')
    plt.savefig('../Figures/SerialCorrOOP.pdf')
    plt.show()

    # Make a plot of serial correlation of OOP medical expenses
    plt.plot(AgeVec + 2, serial_corr_data, '-r')
    plt.plot(AgeVec + 2, serial_corr_sim, '-b')
    plt.xlabel('Age')
    plt.ylabel('$R^2$ of regression of $\log(OOP_{t})$ on $\log(OOP_{t-1})$')
    plt.legend(['HRS data', 'Model'], loc=1)
    plt.show()

    # Calculate mortality probability by age and income quintile in simulated data
    MortByIncAge_data = Data.MortByIncAge
    MortByIncAge_sim = np.zeros((5, 15))
    MortByAge_sim = np.zeros(15)
    for t in range(15):
        THESE = np.logical_and(Active[t, :], InDataSpan[t, :])
        Weight = WeightHist[t + 1, THESE]
        WeightSum = np.sum(Weight)
        Mort = MortHist[t + 1, THESE]
        MortByAge_sim[t] = np.dot(Mort, Weight) / WeightSum
        for i in range(5):
            right_inc = IncQuint == i + 1
            these = np.logical_and(THESE, right_inc)
            Mort = MortHist[t + 1, these]
            Weight = WeightHist[t + 1, these]
            WeightSum = np.sum(Weight)
            MortByIncAge_sim[i, t] = np.dot(Mort, Weight) / WeightSum

    # Plot mortality probability by age and income quintile
    income_colors = ['b', 'r', 'g', 'm', 'c']
    for i in range(5):
        plt.plot(AgeVec, MortByIncAge_sim[i, :] - MortByAge_sim,
                 '-' + income_colors[i])
    for i in range(5):
        plt.plot(AgeVec, MortByIncAge_data[i, :] - MortByAge_sim,
                 '.' + income_colors[i])
    plt.xlabel('Age')
    plt.ylabel('Relative death probability (biannual)')
    plt.title('Death Probability by Income Quintile')
    plt.legend([
        'Bottom quintile', 'Second quintile', 'Third quintile',
        'Fourth quintile', 'Top quintile'
    ],
               loc=2)
    plt.savefig('../Figures/MortByIncAge.pdf')
    plt.show()

    # Plot the 99% confidence band of the health production function
    mean = np.array([-2.13369276099, 1.71842956397])
    covar = np.array([[0.02248322, 0.01628292], [0.01628308, 0.01564192]])
    dstn = multivariate_normal(mean, covar)
    N = 10000
    M = 201
    draws = dstn.rvs(10000)
    MedVec = np.linspace(0., 1.5, M)
    func_data = np.zeros((N, M))

    def makeHealthProdFunc(LogSlope, LogCurve):
        LogJerk = 15.6
        tempw = np.exp(LogJerk)
        HealthProd0 = 1. - tempw
        tempx = np.exp(
            LogSlope)  # Slope of health production function at iLvl=0
        HealthProd2 = np.exp(LogJerk - LogCurve)
        HealthProdFunc = lambda i: tempx / HealthProd0 * (
            (i * HealthProd2**(
                (1. - HealthProd0) / HealthProd0) + HealthProd2**
             (1. / HealthProd0))**HealthProd0 - HealthProd2)
        return HealthProdFunc

    for n in range(N):
        f = makeHealthProdFunc(draws[n, 0], draws[n, 1])
        func_data[n, :] = f(MedVec)

    f = makeHealthProdFunc(Params.test_param_vec[25],
                           Params.test_param_vec[26])
    CI_array = np.zeros((M, 2))
    for m in range(M):
        CI_array[m, :] = getPercentiles(func_data[:, m],
                                        percentiles=[0.025, 0.975])
    health_prod = f(MedVec)

    plt.plot(MedVec, health_prod, '-r')
    plt.plot(MedVec, CI_array[:, 0], '--k', linewidth=0.5)
    plt.plot(MedVec, CI_array[:, 1], '--k', linewidth=0.5)
    plt.xlim([-0.005, 1.5])
    plt.ylim([0., None])
    plt.xlabel('Health investment $n_{it}$, \$10,000 (y2000)')
    plt.ylabel('Health produced ')
    plt.title('Estimated Health Production Function')
    plt.legend([
        'Estimated health production function',
        'Pointwise 95% confidence bounds'
    ],
               loc=4)
    plt.savefig('../Figures/HealthProdFunc.pdf')
    plt.show()
示例#4
0
def FagerengObjFunc(center, spread, verbose=False):
    '''
    Objective function for the quick and dirty structural estimation to fit
    Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon
    consumption-saving model (with permanent and transitory income shocks).
    
    Parameters
    ----------
    center : float
        Center of the uniform distribution of discount factors.
    spread : float
        Width of the uniform distribution of discount factors.
    verbose : bool
        When True, print to screen MPC table for these parameters.  When False,
        print (center, spread, distance).
        
    Returns
    -------
    distance : float
        Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs.
    '''
    # Give our consumer types the requested discount factor distribution
    beta_set = approxUniform(N=TypeCount,
                             bot=center - spread,
                             top=center + spread)[1]
    for j in range(TypeCount):
        EstTypeList[j](DiscFac=beta_set[j])

    # Solve and simulate all consumer types, then gather their wealth levels
    multiThreadCommands(
        EstTypeList,
        ['solve()', 'initializeSim()', 'simulate()', 'unpackcFunc()'])
    WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])

    # Get wealth quartile cutoffs and distribute them to each consumer type
    quartile_cuts = getPercentiles(WealthNow, percentiles=[0.25, 0.50, 0.75])
    for ThisType in EstTypeList:
        WealthQ = np.zeros(ThisType.AgentCount, dtype=int)
        for n in range(3):
            WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1
        ThisType(WealthQ=WealthQ)

    # Keep track of MPC sets in lists of lists of arrays
    MPC_set_list = [[[], [], [], []], [[], [], [], []], [[], [], [], []],
                    [[], [], [], []]]

    # Calculate the MPC for each of the four lottery sizes for all agents
    for ThisType in EstTypeList:
        ThisType.simulate(1)
        c_base = ThisType.cNrmNow
        MPC_this_type = np.zeros((ThisType.AgentCount, 4))
        for k in range(4):  # Get MPC for all agents of this type
            Llvl = lottery_size[k]
            Lnrm = Llvl / ThisType.pLvlNow
            if do_secant:
                SplurgeNrm = Splurge / ThisType.pLvlNow
                mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm
                cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm
                MPC_this_type[:, k] = (cAdj - c_base) / Lnrm
            else:
                mAdj = ThisType.mNrmNow + Lnrm
                MPC_this_type[:, k] = cAdj = ThisType.cFunc[0].derivative(mAdj)

        # Sort the MPCs into the proper MPC sets
        for q in range(4):
            these = ThisType.WealthQ == q
            for k in range(4):
                MPC_set_list[k][q].append(MPC_this_type[these, k])

    # Calculate average within each MPC set
    simulated_MPC_means = np.zeros((4, 4))
    for k in range(4):
        for q in range(4):
            MPC_array = np.concatenate(MPC_set_list[k][q])
            simulated_MPC_means[k, q] = np.mean(MPC_array)

    # Calculate Euclidean distance between simulated MPC averages and Table 9 targets
    diff = simulated_MPC_means - MPC_target
    if drop_corner:
        diff[0, 0] = 0.0
    distance = np.sqrt(np.sum((diff)**2))
    if verbose:
        print(simulated_MPC_means)
    else:
        print(center, spread, distance)
    return distance
    def calcStats(self, aLvlNow, pLvlNow, MPCnow, TranShkNow, EmpNow, t_age,
                  LorenzBool, ManyStatsBool):
        '''
        Calculate various statistics about the current population in the economy.
        
        Parameters
        ----------
        aLvlNow : [np.array]
            Arrays with end-of-period assets, listed by each ConsumerType in self.agents.
        pLvlNow : [np.array]
            Arrays with permanent income levels, listed by each ConsumerType in self.agents.
        MPCnow : [np.array]
            Arrays with marginal propensity to consume, listed by each ConsumerType in self.agents.
        TranShkNow : [np.array]
            Arrays with transitory income shocks, listed by each ConsumerType in self.agents.
        EmpNow : [np.array]
            Arrays with employment states: True if employed, False otherwise.
        t_age : [np.array]
            Arrays with periods elapsed since model entry, listed by each ConsumerType in self.agents.
        LorenzBool: bool
            Indicator for whether the Lorenz target points should be calculated.  Usually False,
            only True when DiscFac has been identified for a particular nabla.
        ManyStatsBool: bool
            Indicator for whether a lot of statistics for tables should be calculated. Usually False,
            only True when parameters have been estimated and we want values for tables.
            
        Returns
        -------
        None
        '''
        # Combine inputs into single arrays
        aLvl = np.hstack(aLvlNow)
        pLvl = np.hstack(pLvlNow)
        age = np.hstack(t_age)
        TranShk = np.hstack(TranShkNow)
        Emp = np.hstack(EmpNow)

        # Calculate the capital to income ratio in the economy
        CohortWeight = self.PopGroFac**(-age)
        CapAgg = np.sum(aLvl * CohortWeight)
        IncAgg = np.sum(pLvl * TranShk * CohortWeight)
        KtoYnow = CapAgg / IncAgg
        self.KtoYnow = KtoYnow

        # Store Lorenz data if requested
        self.LorenzLong = np.nan
        if LorenzBool:
            order = np.argsort(aLvl)
            aLvl = aLvl[order]
            CohortWeight = CohortWeight[order]
            wealth_shares = getLorenzShares(aLvl,
                                            weights=CohortWeight,
                                            percentiles=self.LorenzPercentiles,
                                            presorted=True)
            self.Lorenz = wealth_shares
            if ManyStatsBool:
                self.LorenzLong = getLorenzShares(aLvl,
                                                  weights=CohortWeight,
                                                  percentiles=np.arange(
                                                      0.01, 1.0, 0.01),
                                                  presorted=True)
        else:
            self.Lorenz = np.nan  # Store nothing if we don't want Lorenz data

        # Calculate a whole bunch of statistics if requested
        if ManyStatsBool:
            # Reshape other inputs
            MPC = np.hstack(MPCnow)

            # Sort other data items if aLvl and CohortWeight were sorted
            if LorenzBool:
                pLvl = pLvl[order]
                MPC = MPC[order]
                TranShk = TranShk[order]
                age = age[order]
                Emp = Emp[order]
            aNrm = aLvl / pLvl  # Normalized assets (wealth ratio)
            IncLvl = TranShk * pLvl  # Labor income this period

            # Calculate overall population MPC and by subpopulations
            #MPCsixmonths = 1.0 - 0.25*((1.0 - MPC) + (1.0 - MPC)**2 + (1.0 - MPC)**3 + (1.0 - MPC)**4)
            MPCsixmonths = 1.0 - (1.0 - MPC)**2
            self.MPCall = np.sum(
                MPCsixmonths * CohortWeight) / np.sum(CohortWeight)
            employed = Emp
            unemployed = np.logical_not(employed)
            if self.T_retire > 0:  # Adjust for the lifecycle model, where agents might be retired instead
                unemployed = np.logical_and(unemployed, age < self.T_retire)
                employed = np.logical_and(employed, age < self.T_retire)
                retired = age >= self.T_retire
            else:
                retired = np.zeros_like(unemployed, dtype=bool)
            self.MPCunemployed = np.sum(
                MPCsixmonths[unemployed] * CohortWeight[unemployed]) / np.sum(
                    CohortWeight[unemployed])
            self.MPCemployed = np.sum(
                MPCsixmonths[employed] * CohortWeight[employed]) / np.sum(
                    CohortWeight[employed])
            self.MPCretired = np.sum(
                MPCsixmonths[retired] * CohortWeight[retired]) / np.sum(
                    CohortWeight[retired])
            self.MPCbyWealthRatio = calcSubpopAvg(MPCsixmonths, aNrm,
                                                  self.cutoffs, CohortWeight)
            self.MPCbyIncome = calcSubpopAvg(MPCsixmonths, IncLvl,
                                             self.cutoffs, CohortWeight)

            # Calculate the wealth quintile distribution of "hand to mouth" consumers
            quintile_cuts = getPercentiles(aLvl,
                                           weights=CohortWeight,
                                           percentiles=[0.2, 0.4, 0.6, 0.8])
            wealth_quintiles = np.ones(aLvl.size, dtype=int)
            wealth_quintiles[aLvl > quintile_cuts[0]] = 2
            wealth_quintiles[aLvl > quintile_cuts[1]] = 3
            wealth_quintiles[aLvl > quintile_cuts[2]] = 4
            wealth_quintiles[aLvl > quintile_cuts[3]] = 5
            MPC_cutoff = getPercentiles(
                MPCsixmonths, weights=CohortWeight, percentiles=[
                    2.0 / 3.0
                ])  # Looking at consumers with MPCs in the top 1/3
            these = MPCsixmonths > MPC_cutoff
            in_top_third_MPC = wealth_quintiles[these]
            temp_weights = CohortWeight[these]
            hand_to_mouth_total = np.sum(temp_weights)
            hand_to_mouth_pct = []
            for q in range(1, 6):
                hand_to_mouth_pct.append(
                    np.sum(temp_weights[in_top_third_MPC == q]) /
                    hand_to_mouth_total)
            self.HandToMouthPct = np.array(hand_to_mouth_pct)

        else:  # If we don't want these stats, just put empty values in history
            self.MPCall = np.nan
            self.MPCunemployed = np.nan
            self.MPCemployed = np.nan
            self.MPCretired = np.nan
            self.MPCbyWealthRatio = np.nan
            self.MPCbyIncome = np.nan
            self.HandToMouthPct = np.nan
示例#6
0
def makeCSTWstats(DiscFac,
                  nabla,
                  this_type_list,
                  age_weight,
                  lorenz_distance=0.0,
                  save_name=None):
    '''
    Displays (and saves) a bunch of statistics.  Separate from makeCSTWresults()
    for compatibility with the aggregate shock model.
    
    Parameters
    ----------
    DiscFac : float
        Center of the uniform distribution of discount factors
    nabla : float
        Width of the uniform distribution of discount factors
    this_type_list : [cstwMPCagent]
        List of agent types in the economy.
    age_weight : np.array
        Age-conditional array of weights for the wealth data.
    lorenz_distance : float
        Distance between simulated and actual Lorenz curves, for display.
    save_name : string
        Name to save the calculated results, for later use in producing figures
        and tables, etc.
        
    Returns
    -------
    none
    '''
    sim_length = this_type_list[0].sim_periods
    sim_wealth = (np.vstack(
        (this_type.W_history for this_type in this_type_list))).flatten()
    sim_wealth_short = (np.vstack(
        (this_type.W_history[0:sim_length, :]
         for this_type in this_type_list))).flatten()
    sim_kappa = (np.vstack(
        (this_type.kappa_history for this_type in this_type_list))).flatten()
    sim_income = (np.vstack((this_type.pHist[0:sim_length, :] *
                             np.asarray(this_type.TranShkHist[0:sim_length, :])
                             for this_type in this_type_list))).flatten()
    sim_ratio = (np.vstack((this_type.W_history[0:sim_length, :] /
                            this_type.pHist[0:sim_length, :]
                            for this_type in this_type_list))).flatten()
    if Params.do_lifecycle:
        sim_unemp = (np.vstack((np.vstack((
            this_type.IncUnemp == this_type.TranShkHist[0:Params.working_T, :],
            np.zeros((Params.retired_T + 1, this_type_list[0].Nagents),
                     dtype=bool)))
                                for this_type in this_type_list))).flatten()
        sim_emp = (np.vstack((np.vstack(
            (this_type.IncUnemp !=
             this_type.TranShkHist[0:Params.working_T, :],
             np.zeros((Params.retired_T + 1, this_type_list[0].Nagents),
                      dtype=bool)))
                              for this_type in this_type_list))).flatten()
        sim_ret = (np.vstack((np.vstack(
            (np.zeros((Params.working_T, this_type_list[0].Nagents),
                      dtype=bool),
             np.ones((Params.retired_T + 1, this_type_list[0].Nagents),
                     dtype=bool)))
                              for this_type in this_type_list))).flatten()
    else:
        sim_unemp = np.vstack(
            (this_type.IncUnemp == this_type.TranShkHist[0:sim_length, :]
             for this_type in this_type_list)).flatten()
        sim_emp = np.vstack(
            (this_type.IncUnemp != this_type.TranShkHist[0:sim_length, :]
             for this_type in this_type_list)).flatten()
        sim_ret = np.zeros(sim_emp.size, dtype=bool)
    sim_weight_all = np.tile(np.repeat(age_weight, this_type_list[0].Nagents),
                             Params.pref_type_count)

    if Params.do_beta_dist and Params.do_lifecycle:
        kappa_mean_by_age_type = (np.mean(np.vstack(
            (this_type.kappa_history for this_type in this_type_list)),
                                          axis=1)).reshape(
                                              (Params.pref_type_count * 3,
                                               DropoutType.T_total + 1))
        kappa_mean_by_age_pref = np.zeros(
            (Params.pref_type_count, DropoutType.T_total + 1)) + np.nan
        for j in range(Params.pref_type_count):
            kappa_mean_by_age_pref[
                j, ] = Params.d_pct * kappa_mean_by_age_type[
                    3 * j + 0, ] + Params.h_pct * kappa_mean_by_age_type[
                        3 * j + 1, ] + Params.c_pct * kappa_mean_by_age_type[
                            3 * j + 2, ]
        kappa_mean_by_age = np.mean(kappa_mean_by_age_pref, axis=0)
        kappa_lo_beta_by_age = kappa_mean_by_age_pref[0, :]
        kappa_hi_beta_by_age = kappa_mean_by_age_pref[Params.pref_type_count -
                                                      1, :]

    lorenz_fig_data = makeLorenzFig(Params.SCF_wealth, Params.SCF_weights,
                                    sim_wealth, sim_weight_all)
    mpc_fig_data = makeMPCfig(sim_kappa, sim_weight_all)

    kappa_all = calcWeightedAvg(
        np.vstack((this_type.kappa_history for this_type in this_type_list)),
        np.tile(age_weight / float(Params.pref_type_count),
                Params.pref_type_count))
    kappa_unemp = np.sum(
        sim_kappa[sim_unemp] * sim_weight_all[sim_unemp]) / np.sum(
            sim_weight_all[sim_unemp])
    kappa_emp = np.sum(sim_kappa[sim_emp] * sim_weight_all[sim_emp]) / np.sum(
        sim_weight_all[sim_emp])
    kappa_ret = np.sum(sim_kappa[sim_ret] * sim_weight_all[sim_ret]) / np.sum(
        sim_weight_all[sim_ret])

    my_cutoffs = [(0.99, 1), (0.9, 1), (0.8, 1), (0.6, 0.8), (0.4, 0.6),
                  (0.2, 0.4), (0.0, 0.2)]
    kappa_by_ratio_groups = calcSubpopAvg(sim_kappa, sim_ratio, my_cutoffs,
                                          sim_weight_all)
    kappa_by_income_groups = calcSubpopAvg(sim_kappa, sim_income, my_cutoffs,
                                           sim_weight_all)

    quintile_points = getPercentiles(sim_wealth_short,
                                     weights=sim_weight_all,
                                     percentiles=[0.2, 0.4, 0.6, 0.8])
    wealth_quintiles = np.ones(sim_wealth_short.size, dtype=int)
    wealth_quintiles[sim_wealth_short > quintile_points[0]] = 2
    wealth_quintiles[sim_wealth_short > quintile_points[1]] = 3
    wealth_quintiles[sim_wealth_short > quintile_points[2]] = 4
    wealth_quintiles[sim_wealth_short > quintile_points[3]] = 5
    MPC_cutoff = getPercentiles(sim_kappa,
                                weights=sim_weight_all,
                                percentiles=[2.0 / 3.0])
    these_quintiles = wealth_quintiles[sim_kappa > MPC_cutoff]
    these_weights = sim_weight_all[sim_kappa > MPC_cutoff]
    hand_to_mouth_total = np.sum(these_weights)
    hand_to_mouth_pct = []
    for q in range(5):
        hand_to_mouth_pct.append(
            np.sum(these_weights[these_quintiles == (q + 1)]) /
            hand_to_mouth_total)

    results_string = 'Estimate is DiscFac=' + str(DiscFac) + ', nabla=' + str(
        nabla) + '\n'
    results_string += 'Lorenz distance is ' + str(lorenz_distance) + '\n'
    results_string += 'Average MPC for all consumers is ' + mystr(
        kappa_all) + '\n'
    results_string += 'Average MPC in the top percentile of W/Y is ' + mystr(
        kappa_by_ratio_groups[0]) + '\n'
    results_string += 'Average MPC in the top decile of W/Y is ' + mystr(
        kappa_by_ratio_groups[1]) + '\n'
    results_string += 'Average MPC in the top quintile of W/Y is ' + mystr(
        kappa_by_ratio_groups[2]) + '\n'
    results_string += 'Average MPC in the second quintile of W/Y is ' + mystr(
        kappa_by_ratio_groups[3]) + '\n'
    results_string += 'Average MPC in the middle quintile of W/Y is ' + mystr(
        kappa_by_ratio_groups[4]) + '\n'
    results_string += 'Average MPC in the fourth quintile of W/Y is ' + mystr(
        kappa_by_ratio_groups[5]) + '\n'
    results_string += 'Average MPC in the bottom quintile of W/Y is ' + mystr(
        kappa_by_ratio_groups[6]) + '\n'
    results_string += 'Average MPC in the top percentile of y is ' + mystr(
        kappa_by_income_groups[0]) + '\n'
    results_string += 'Average MPC in the top decile of y is ' + mystr(
        kappa_by_income_groups[1]) + '\n'
    results_string += 'Average MPC in the top quintile of y is ' + mystr(
        kappa_by_income_groups[2]) + '\n'
    results_string += 'Average MPC in the second quintile of y is ' + mystr(
        kappa_by_income_groups[3]) + '\n'
    results_string += 'Average MPC in the middle quintile of y is ' + mystr(
        kappa_by_income_groups[4]) + '\n'
    results_string += 'Average MPC in the fourth quintile of y is ' + mystr(
        kappa_by_income_groups[5]) + '\n'
    results_string += 'Average MPC in the bottom quintile of y is ' + mystr(
        kappa_by_income_groups[6]) + '\n'
    results_string += 'Average MPC for the employed is ' + mystr(
        kappa_emp) + '\n'
    results_string += 'Average MPC for the unemployed is ' + mystr(
        kappa_unemp) + '\n'
    results_string += 'Average MPC for the retired is ' + mystr(
        kappa_ret) + '\n'
    results_string += 'Of the population with the 1/3 highest MPCs...' + '\n'
    results_string += mystr(
        hand_to_mouth_pct[0] *
        100) + '% are in the bottom wealth quintile,' + '\n'
    results_string += mystr(
        hand_to_mouth_pct[1] *
        100) + '% are in the second wealth quintile,' + '\n'
    results_string += mystr(hand_to_mouth_pct[2] *
                            100) + '% are in the third wealth quintile,' + '\n'
    results_string += mystr(
        hand_to_mouth_pct[3] *
        100) + '% are in the fourth wealth quintile,' + '\n'
    results_string += 'and ' + mystr(
        hand_to_mouth_pct[4] *
        100) + '% are in the top wealth quintile.' + '\n'
    print(results_string)

    if save_name is not None:
        with open('./Results/' + save_name + 'LorenzFig.txt', 'w') as f:
            my_writer = csv.writer(
                f,
                delimiter='\t',
            )
            for j in range(len(lorenz_fig_data[0])):
                my_writer.writerow([
                    lorenz_fig_data[0][j], lorenz_fig_data[1][j],
                    lorenz_fig_data[2][j]
                ])
            f.close()
        with open('./Results/' + save_name + 'MPCfig.txt', 'w') as f:
            my_writer = csv.writer(f, delimiter='\t')
            for j in range(len(mpc_fig_data[0])):
                my_writer.writerow([lorenz_fig_data[0][j], mpc_fig_data[1][j]])
            f.close()
        if Params.do_beta_dist and Params.do_lifecycle:
            with open('./Results/' + save_name + 'KappaByAge.txt', 'w') as f:
                my_writer = csv.writer(f, delimiter='\t')
                for j in range(len(kappa_mean_by_age)):
                    my_writer.writerow([
                        kappa_mean_by_age[j], kappa_lo_beta_by_age[j],
                        kappa_hi_beta_by_age[j]
                    ])
                f.close()
        with open('./Results/' + save_name + 'Results.txt', 'w') as f:
            f.write(results_string)
            f.close()
     
 # Make a boolean array of usable observations (for non-mortality moments)
 BelowCohort16 = np.tile(np.reshape(cohort_data,(1,obs)),(8,1)) < 16
 Alive = h_data > 0.
 NotInit = np.logical_not(InitBoolArray)
 Useable = np.logical_and(BelowCohort16,np.logical_and(Alive,NotInit))
 
 # Calculate health quintiles at data entry by age (and overwrite old health tertile info)
 health_tertile_cuts = np.zeros((2,15))
 health_quintile_cuts = np.zeros((4,15))
 health_tert_data = np.zeros_like(health_tert_data_alt,dtype=int)
 health_quint_data = np.zeros_like(health_tert_data_alt,dtype=int)
 for a in range(15):
     these = np.logical_and(Alive,AgeBoolArray[:,:,a])
     health_temp = h_data[these]
     health_quintile_cuts[:,a] = getPercentiles(health_temp,percentiles=[0.2,0.4,0.6,0.8])
     health_tertile_cuts[:,a] = getPercentiles(health_temp,percentiles=[0.333,0.666])
     those = BornBoolArray[a,:]
     h_init_temp = h_init[those]
     health_quint_data[those] = np.searchsorted(health_quintile_cuts[:,a],h_init_temp) + 1
     health_tert_data[those] = np.searchsorted(health_tertile_cuts[:,a],h_init_temp) + 1
 
 # Make data objects for the health production pre-estimation
 UseableAlt = np.logical_and(BelowCohort16,Alive)
 inc_quint_data_rep = np.tile(np.reshape(inc_quint_data,(1,obs)),(8,1))
 wealth_quint_data_rep = np.tile(np.reshape(wealth_quint_data,(1,obs)),(8,1))
 sex_data_rep = np.tile(np.reshape(sex_data,(1,obs)),(8,1))
 WealthArraysBySexIncAge = []
 HealthArraysBySexIncAge = []
 WealthQuintArraysBySexIncAge = []
 for s in range(2):
示例#8
0
文件: cstwMPC.py 项目: chiomh/HARK
def makeCSTWstats(DiscFac,nabla,this_type_list,age_weight,lorenz_distance=0.0,save_name=None):
    '''
    Displays (and saves) a bunch of statistics.  Separate from makeCSTWresults()
    for compatibility with the aggregate shock model.
    
    Parameters
    ----------
    DiscFac : float
        Center of the uniform distribution of discount factors
    nabla : float
        Width of the uniform distribution of discount factors
    this_type_list : [cstwMPCagent]
        List of agent types in the economy.
    age_weight : np.array
        Age-conditional array of weights for the wealth data.
    lorenz_distance : float
        Distance between simulated and actual Lorenz curves, for display.
    save_name : string
        Name to save the calculated results, for later use in producing figures
        and tables, etc.
        
    Returns
    -------
    none
    '''
    sim_length = this_type_list[0].sim_periods
    sim_wealth = (np.vstack((this_type.W_history for this_type in this_type_list))).flatten()
    sim_wealth_short = (np.vstack((this_type.W_history[0:sim_length,:] for this_type in this_type_list))).flatten()
    sim_kappa = (np.vstack((this_type.kappa_history for this_type in this_type_list))).flatten()
    sim_income = (np.vstack((this_type.pHist[0:sim_length,:]*np.asarray(this_type.TranShkHist[0:sim_length,:]) for this_type in this_type_list))).flatten()
    sim_ratio = (np.vstack((this_type.W_history[0:sim_length,:]/this_type.pHist[0:sim_length,:] for this_type in this_type_list))).flatten()
    if Params.do_lifecycle:
        sim_unemp = (np.vstack((np.vstack((this_type.IncUnemp == this_type.TranShkHist[0:Params.working_T,:],np.zeros((Params.retired_T+1,this_type_list[0].Nagents),dtype=bool))) for this_type in this_type_list))).flatten()
        sim_emp = (np.vstack((np.vstack((this_type.IncUnemp != this_type.TranShkHist[0:Params.working_T,:],np.zeros((Params.retired_T+1,this_type_list[0].Nagents),dtype=bool))) for this_type in this_type_list))).flatten()
        sim_ret = (np.vstack((np.vstack((np.zeros((Params.working_T,this_type_list[0].Nagents),dtype=bool),np.ones((Params.retired_T+1,this_type_list[0].Nagents),dtype=bool))) for this_type in this_type_list))).flatten()
    else:
        sim_unemp = np.vstack((this_type.IncUnemp == this_type.TranShkHist[0:sim_length,:] for this_type in this_type_list)).flatten()
        sim_emp = np.vstack((this_type.IncUnemp != this_type.TranShkHist[0:sim_length,:] for this_type in this_type_list)).flatten()
        sim_ret = np.zeros(sim_emp.size,dtype=bool)
    sim_weight_all = np.tile(np.repeat(age_weight,this_type_list[0].Nagents),Params.pref_type_count)
    
    if Params.do_beta_dist and Params.do_lifecycle:
        kappa_mean_by_age_type = (np.mean(np.vstack((this_type.kappa_history for this_type in this_type_list)),axis=1)).reshape((Params.pref_type_count*3,DropoutType.T_total+1))
        kappa_mean_by_age_pref = np.zeros((Params.pref_type_count,DropoutType.T_total+1)) + np.nan
        for j in range(Params.pref_type_count):
            kappa_mean_by_age_pref[j,] = Params.d_pct*kappa_mean_by_age_type[3*j+0,] + Params.h_pct*kappa_mean_by_age_type[3*j+1,] + Params.c_pct*kappa_mean_by_age_type[3*j+2,] 
        kappa_mean_by_age = np.mean(kappa_mean_by_age_pref,axis=0)
        kappa_lo_beta_by_age = kappa_mean_by_age_pref[0,:]
        kappa_hi_beta_by_age = kappa_mean_by_age_pref[Params.pref_type_count-1,:]
    
    lorenz_fig_data = makeLorenzFig(Params.SCF_wealth,Params.SCF_weights,sim_wealth,sim_weight_all)
    mpc_fig_data = makeMPCfig(sim_kappa,sim_weight_all)
    
    kappa_all = calcWeightedAvg(np.vstack((this_type.kappa_history for this_type in this_type_list)),np.tile(age_weight/float(Params.pref_type_count),Params.pref_type_count))
    kappa_unemp = np.sum(sim_kappa[sim_unemp]*sim_weight_all[sim_unemp])/np.sum(sim_weight_all[sim_unemp])
    kappa_emp = np.sum(sim_kappa[sim_emp]*sim_weight_all[sim_emp])/np.sum(sim_weight_all[sim_emp])
    kappa_ret = np.sum(sim_kappa[sim_ret]*sim_weight_all[sim_ret])/np.sum(sim_weight_all[sim_ret])
    
    my_cutoffs = [(0.99,1),(0.9,1),(0.8,1),(0.6,0.8),(0.4,0.6),(0.2,0.4),(0.0,0.2)]
    kappa_by_ratio_groups = calcSubpopAvg(sim_kappa,sim_ratio,my_cutoffs,sim_weight_all)
    kappa_by_income_groups = calcSubpopAvg(sim_kappa,sim_income,my_cutoffs,sim_weight_all)
    
    quintile_points = getPercentiles(sim_wealth_short,weights=sim_weight_all,percentiles=[0.2, 0.4, 0.6, 0.8])
    wealth_quintiles = np.ones(sim_wealth_short.size,dtype=int)
    wealth_quintiles[sim_wealth_short > quintile_points[0]] = 2
    wealth_quintiles[sim_wealth_short > quintile_points[1]] = 3
    wealth_quintiles[sim_wealth_short > quintile_points[2]] = 4
    wealth_quintiles[sim_wealth_short > quintile_points[3]] = 5
    MPC_cutoff = getPercentiles(sim_kappa,weights=sim_weight_all,percentiles=[2.0/3.0])
    these_quintiles = wealth_quintiles[sim_kappa > MPC_cutoff]
    these_weights = sim_weight_all[sim_kappa > MPC_cutoff]
    hand_to_mouth_total = np.sum(these_weights)
    hand_to_mouth_pct = []
    for q in range(5):
        hand_to_mouth_pct.append(np.sum(these_weights[these_quintiles == (q+1)])/hand_to_mouth_total)
    
    results_string = 'Estimate is DiscFac=' + str(DiscFac) + ', nabla=' + str(nabla) + '\n'
    results_string += 'Lorenz distance is ' + str(lorenz_distance) + '\n'
    results_string += 'Average MPC for all consumers is ' + mystr(kappa_all) + '\n'
    results_string += 'Average MPC in the top percentile of W/Y is ' + mystr(kappa_by_ratio_groups[0]) + '\n'
    results_string += 'Average MPC in the top decile of W/Y is ' + mystr(kappa_by_ratio_groups[1]) + '\n'
    results_string += 'Average MPC in the top quintile of W/Y is ' + mystr(kappa_by_ratio_groups[2]) + '\n'
    results_string += 'Average MPC in the second quintile of W/Y is ' + mystr(kappa_by_ratio_groups[3]) + '\n'
    results_string += 'Average MPC in the middle quintile of W/Y is ' + mystr(kappa_by_ratio_groups[4]) + '\n'
    results_string += 'Average MPC in the fourth quintile of W/Y is ' + mystr(kappa_by_ratio_groups[5]) + '\n'
    results_string += 'Average MPC in the bottom quintile of W/Y is ' + mystr(kappa_by_ratio_groups[6]) + '\n'
    results_string += 'Average MPC in the top percentile of y is ' + mystr(kappa_by_income_groups[0]) + '\n'
    results_string += 'Average MPC in the top decile of y is ' + mystr(kappa_by_income_groups[1]) + '\n'
    results_string += 'Average MPC in the top quintile of y is ' + mystr(kappa_by_income_groups[2]) + '\n'
    results_string += 'Average MPC in the second quintile of y is ' + mystr(kappa_by_income_groups[3]) + '\n'
    results_string += 'Average MPC in the middle quintile of y is ' + mystr(kappa_by_income_groups[4]) + '\n'
    results_string += 'Average MPC in the fourth quintile of y is ' + mystr(kappa_by_income_groups[5]) + '\n'
    results_string += 'Average MPC in the bottom quintile of y is ' + mystr(kappa_by_income_groups[6]) + '\n'
    results_string += 'Average MPC for the employed is ' + mystr(kappa_emp) + '\n'
    results_string += 'Average MPC for the unemployed is ' + mystr(kappa_unemp) + '\n'
    results_string += 'Average MPC for the retired is ' + mystr(kappa_ret) + '\n'
    results_string += 'Of the population with the 1/3 highest MPCs...' + '\n'
    results_string += mystr(hand_to_mouth_pct[0]*100) + '% are in the bottom wealth quintile,' + '\n'
    results_string += mystr(hand_to_mouth_pct[1]*100) + '% are in the second wealth quintile,' + '\n'
    results_string += mystr(hand_to_mouth_pct[2]*100) + '% are in the third wealth quintile,' + '\n'
    results_string += mystr(hand_to_mouth_pct[3]*100) + '% are in the fourth wealth quintile,' + '\n'
    results_string += 'and ' + mystr(hand_to_mouth_pct[4]*100) + '% are in the top wealth quintile.' + '\n'
    print(results_string)
    
    if save_name is not None:
        with open('./Results/' + save_name + 'LorenzFig.txt','w') as f:
            my_writer = csv.writer(f, delimiter='\t',)
            for j in range(len(lorenz_fig_data[0])):
                my_writer.writerow([lorenz_fig_data[0][j], lorenz_fig_data[1][j], lorenz_fig_data[2][j]])
            f.close()
        with open('./Results/' + save_name + 'MPCfig.txt','w') as f:
            my_writer = csv.writer(f, delimiter='\t')
            for j in range(len(mpc_fig_data[0])):
                my_writer.writerow([lorenz_fig_data[0][j], mpc_fig_data[1][j]])
            f.close()
        if Params.do_beta_dist and Params.do_lifecycle:
            with open('./Results/' + save_name + 'KappaByAge.txt','w') as f:
                my_writer = csv.writer(f, delimiter='\t')
                for j in range(len(kappa_mean_by_age)):
                    my_writer.writerow([kappa_mean_by_age[j], kappa_lo_beta_by_age[j], kappa_hi_beta_by_age[j]])
                f.close()
        with open('./Results/' + save_name + 'Results.txt','w') as f:
            f.write(results_string)
            f.close()
示例#9
0
 def calcStats(self,aLvlNow,pLvlNow,MPCnow,TranShkNow,EmpNow,t_age,LorenzBool,ManyStatsBool):
     '''
     Calculate various statistics about the current population in the economy.
     
     Parameters
     ----------
     aLvlNow : [np.array]
         Arrays with end-of-period assets, listed by each ConsumerType in self.agents.
     pLvlNow : [np.array]
         Arrays with permanent income levels, listed by each ConsumerType in self.agents.
     MPCnow : [np.array]
         Arrays with marginal propensity to consume, listed by each ConsumerType in self.agents.
     TranShkNow : [np.array]
         Arrays with transitory income shocks, listed by each ConsumerType in self.agents.
     EmpNow : [np.array]
         Arrays with employment states: True if employed, False otherwise.
     t_age : [np.array]
         Arrays with periods elapsed since model entry, listed by each ConsumerType in self.agents.
     LorenzBool: bool
         Indicator for whether the Lorenz target points should be calculated.  Usually False,
         only True when DiscFac has been identified for a particular nabla.
     ManyStatsBool: bool
         Indicator for whether a lot of statistics for tables should be calculated. Usually False,
         only True when parameters have been estimated and we want values for tables.
         
     Returns
     -------
     None
     '''
     # Combine inputs into single arrays
     aLvl = np.hstack(aLvlNow)
     pLvl = np.hstack(pLvlNow)
     age  = np.hstack(t_age)
     TranShk = np.hstack(TranShkNow)
     Emp = np.hstack(EmpNow)
     
     # Calculate the capital to income ratio in the economy
     CohortWeight = self.PopGroFac**(-age)
     CapAgg = np.sum(aLvl*CohortWeight)
     IncAgg = np.sum(pLvl*TranShk*CohortWeight)
     KtoYnow = CapAgg/IncAgg
     self.KtoYnow = KtoYnow
     
     # Store Lorenz data if requested
     self.LorenzLong = np.nan
     if LorenzBool:
         order = np.argsort(aLvl)
         aLvl = aLvl[order]
         CohortWeight = CohortWeight[order]
         wealth_shares = getLorenzShares(aLvl,weights=CohortWeight,percentiles=self.LorenzPercentiles,presorted=True)
         self.Lorenz = wealth_shares
         if ManyStatsBool:
             self.LorenzLong = getLorenzShares(aLvl,weights=CohortWeight,percentiles=np.arange(0.01,1.0,0.01),presorted=True)                
     else:
         self.Lorenz = np.nan # Store nothing if we don't want Lorenz data
         
     # Calculate a whole bunch of statistics if requested
     if ManyStatsBool:
         # Reshape other inputs
         MPC  = np.hstack(MPCnow)
         
         # Sort other data items if aLvl and CohortWeight were sorted
         if LorenzBool:
             pLvl = pLvl[order]
             MPC  = MPC[order]
             TranShk = TranShk[order]
             age = age[order]
             Emp = Emp[order]
         aNrm = aLvl/pLvl # Normalized assets (wealth ratio)
         IncLvl = TranShk*pLvl # Labor income this period
             
         # Calculate overall population MPC and by subpopulations
         MPCannual = 1.0 - (1.0 - MPC)**4
         self.MPCall = np.sum(MPCannual*CohortWeight)/np.sum(CohortWeight)
         employed =  Emp
         unemployed = np.logical_not(employed)
         if self.T_retire > 0: # Adjust for the lifecycle model, where agents might be retired instead
             unemployed = np.logical_and(unemployed,age < self.T_retire)
             employed   = np.logical_and(employed,age < self.T_retire)
             retired    = age >= self.T_retire
         else:
             retired    = np.zeros_like(unemployed,dtype=bool)
         self.MPCunemployed = np.sum(MPCannual[unemployed]*CohortWeight[unemployed])/np.sum(CohortWeight[unemployed])
         self.MPCemployed   = np.sum(MPCannual[employed]*CohortWeight[employed])/np.sum(CohortWeight[employed])
         self.MPCretired    = np.sum(MPCannual[retired]*CohortWeight[retired])/np.sum(CohortWeight[retired])
         self.MPCbyWealthRatio = calcSubpopAvg(MPCannual,aNrm,self.cutoffs,CohortWeight)
         self.MPCbyIncome      = calcSubpopAvg(MPCannual,IncLvl,self.cutoffs,CohortWeight)
         
         # Calculate the wealth quintile distribution of "hand to mouth" consumers
         quintile_cuts = getPercentiles(aLvl,weights=CohortWeight,percentiles=[0.2, 0.4, 0.6, 0.8])
         wealth_quintiles = np.ones(aLvl.size,dtype=int)
         wealth_quintiles[aLvl > quintile_cuts[0]] = 2
         wealth_quintiles[aLvl > quintile_cuts[1]] = 3
         wealth_quintiles[aLvl > quintile_cuts[2]] = 4
         wealth_quintiles[aLvl > quintile_cuts[3]] = 5
         MPC_cutoff = getPercentiles(MPCannual,weights=CohortWeight,percentiles=[2.0/3.0]) # Looking at consumers with MPCs in the top 1/3
         these = MPCannual > MPC_cutoff
         in_top_third_MPC = wealth_quintiles[these]
         temp_weights = CohortWeight[these]
         hand_to_mouth_total = np.sum(temp_weights)
         hand_to_mouth_pct = []
         for q in range(1,6):
             hand_to_mouth_pct.append(np.sum(temp_weights[in_top_third_MPC == q])/hand_to_mouth_total)
         self.HandToMouthPct = np.array(hand_to_mouth_pct)
         
     else: # If we don't want these stats, just put empty values in history
         self.MPCall = np.nan
         self.MPCunemployed = np.nan
         self.MPCemployed = np.nan
         self.MPCretired = np.nan
         self.MPCbyWealthRatio = np.nan
         self.MPCbyIncome = np.nan
         self.HandToMouthPct = np.nan