1010from policyengine_uk_data .storage import STORAGE_FOLDER
1111from policyengine_uk .data import UKSingleYearDataset
1212from policyengine_uk import Microsimulation
13+ from policyengine_uk_data .utils .qrf import QRF
1314
1415WAS_TAB_FOLDER = STORAGE_FOLDER / "was_2006_20"
1516
5253 "non_residential_property_value" ,
5354 "savings" ,
5455 "num_vehicles" ,
56+ "student_loan_balance" ,
5557]
5658
59+ WAS_RENAMES = {
60+ "R7xshhwgt" : "household_weight" ,
61+ # Components for estimating land holdings.
62+ "DVLUKValR7_sum" : "owned_land" , # In the UK.
63+ "DVPropertyR7" : "property_wealth" ,
64+ "DVFESHARESR7_aggr" : "emp_shares_options" ,
65+ "DVFShUKVR7_aggr" : "uk_shares" ,
66+ "DVIISAVR7_aggr" : "investment_isas" ,
67+ "DVFCollVR7_aggr" : "unit_investment_trusts" ,
68+ "TotpenR7_aggr" : "pensions" ,
69+ "DvvalDBTR7_aggr" : "db_pensions" ,
70+ # Predictors for fusing to FRS.
71+ "dvtotgirR7" : "gross_income" ,
72+ "NumAdultW7" : "num_adults" ,
73+ "NumCh18W7" : "num_children" ,
74+ # Household Gross Annual income from occupational or private pensions
75+ "DVGIPPENR7_AGGR" : "private_pension_income" ,
76+ "DVGISER7_AGGR" : "self_employment_income" ,
77+ # Household Gross annual income from investments
78+ "DVGIINVR7_aggr" : "capital_income" ,
79+ # Household Total Annual Gross employee income
80+ "DVGIEMPR7_AGGR" : "employment_income" ,
81+ "HBedrmW7" : "num_bedrooms" ,
82+ "GORR7" : "region" ,
83+ "DVPriRntW7" : "is_renter" , # {1, 2} TODO: Get codebook values.
84+ "CTAmtW7" : "council_tax" ,
85+ # Other columns for reference.
86+ "DVLOSValR7_sum" : "non_uk_land" ,
87+ "HFINWNTR7_Sum" : "net_financial_wealth" ,
88+ "DVLUKDebtR7_sum" : "uk_land_debt" ,
89+ "HFINWR7_Sum" : "gross_financial_wealth" ,
90+ "TotWlthR7" : "wealth" ,
91+ "DVhvalueR7" : "main_residence_value" ,
92+ "DVHseValR7_sum" : "other_residential_property_value" ,
93+ "DVBlDValR7_sum" : "non_residential_property_value" ,
94+ "DVTotinc_bhcR7" : "household_net_income" ,
95+ "DVSaValR7_aggr" : "savings" ,
96+ "vcarnr7" : "num_vehicles" ,
97+ "Tot_LosR7_aggr" : "total_loans" ,
98+ "Tot_los_exc_SLCR7_aggr" : "total_loans_exc_slc" ,
99+ }
100+
57101
58102def generate_was_table (was : pd .DataFrame ):
59103 """
@@ -70,47 +114,7 @@ def generate_was_table(was: pd.DataFrame):
70114 to_remove = []
71115 to_add = {}
72116
73- RENAMES = {
74- "R7xshhwgt" : "household_weight" ,
75- # Components for estimating land holdings.
76- "DVLUKValR7_sum" : "owned_land" , # In the UK.
77- "DVPropertyR7" : "property_wealth" ,
78- "DVFESHARESR7_aggr" : "emp_shares_options" ,
79- "DVFShUKVR7_aggr" : "uk_shares" ,
80- "DVIISAVR7_aggr" : "investment_isas" ,
81- "DVFCollVR7_aggr" : "unit_investment_trusts" ,
82- "TotpenR7_aggr" : "pensions" ,
83- "DvvalDBTR7_aggr" : "db_pensions" ,
84- # Predictors for fusing to FRS.
85- "dvtotgirR7" : "gross_income" ,
86- "NumAdultW7" : "num_adults" ,
87- "NumCh18W7" : "num_children" ,
88- # Household Gross Annual income from occupational or private pensions
89- "DVGIPPENR7_AGGR" : "private_pension_income" ,
90- "DVGISER7_AGGR" : "self_employment_income" ,
91- # Household Gross annual income from investments
92- "DVGIINVR7_aggr" : "capital_income" ,
93- # Household Total Annual Gross employee income
94- "DVGIEMPR7_AGGR" : "employment_income" ,
95- "HBedrmW7" : "num_bedrooms" ,
96- "GORR7" : "region" ,
97- "DVPriRntW7" : "is_renter" , # {1, 2} TODO: Get codebook values.
98- "CTAmtW7" : "council_tax" ,
99- # Other columns for reference.
100- "DVLOSValR7_sum" : "non_uk_land" ,
101- "HFINWNTR7_Sum" : "net_financial_wealth" ,
102- "DVLUKDebtR7_sum" : "uk_land_debt" ,
103- "HFINWR7_Sum" : "gross_financial_wealth" ,
104- "TotWlthR7" : "wealth" ,
105- "DVhvalueR7" : "main_residence_value" ,
106- "DVHseValR7_sum" : "other_residential_property_value" ,
107- "DVBlDValR7_sum" : "non_residential_property_value" ,
108- "DVTotinc_bhcR7" : "household_net_income" ,
109- "DVSaValR7_aggr" : "savings" ,
110- "vcarnr7" : "num_vehicles" ,
111- }
112-
113- RENAMES = {x .lower (): y for x , y in RENAMES .items ()}
117+ RENAMES = {x .lower (): y for x , y in WAS_RENAMES .items ()}
114118
115119 for key in RENAMES :
116120 key = key .lower ()
@@ -145,19 +149,24 @@ def generate_was_table(was: pd.DataFrame):
145149 "unit_investment_trusts" ,
146150 ]
147151 ].sum (axis = 1 )
152+ was ["student_loan_balance" ] = was ["total_loans" ] - was ["total_loans_exc_slc" ]
148153 was ["region" ] = was ["region" ].map (REGIONS )
149154 return was
150155
151156
157+ def _wealth_model_outputs_are_current (model : QRF ) -> bool :
158+ """Check whether a cached wealth model includes all current output columns."""
159+ trained_outputs = getattr (model .model , "imputed_variables" , None )
160+ return list (trained_outputs ) == IMPUTE_VARIABLES
161+
162+
152163def save_imputation_models ():
153164 """
154165 Train and save wealth imputation model.
155166
156167 Returns:
157168 Trained QRF model.
158169 """
159- from policyengine_uk_data .utils .qrf import QRF
160-
161170 was = pd .read_csv (
162171 WAS_TAB_FOLDER / "was_round_7_hhold_eul_march_2022.tab" ,
163172 sep = "\t " ,
@@ -185,10 +194,10 @@ def create_wealth_model(overwrite_existing: bool = False):
185194 Returns:
186195 QRF model for wealth imputation.
187196 """
188- from policyengine_uk_data .utils .qrf import QRF
189-
190197 if (STORAGE_FOLDER / "wealth.pkl" ).exists () and not overwrite_existing :
191- return QRF (file_path = STORAGE_FOLDER / "wealth.pkl" )
198+ wealth = QRF (file_path = STORAGE_FOLDER / "wealth.pkl" )
199+ if _wealth_model_outputs_are_current (wealth ):
200+ return wealth
192201 return save_imputation_models ()
193202
194203
0 commit comments