-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathdataset_schema.py
More file actions
118 lines (102 loc) · 3.85 KB
/
Copy pathdataset_schema.py
File metadata and controls
118 lines (102 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import pandas as pd
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from policyengine_uk import Microsimulation
from pathlib import Path
import h5py
class UKDataset:
person: pd.DataFrame
benunit: pd.DataFrame
household: pd.DataFrame
@staticmethod
def validate_file_path(file_path: str):
if not file_path.endswith(".h5"):
raise ValueError("File path must end with '.h5' for UKDataset.")
if not Path(file_path).exists():
raise FileNotFoundError(f"File not found: {file_path}")
# Check if the file contains time_period, person, benunit, and household datasets
with h5py.File(file_path, "r") as f:
required_datasets = [
"time_period",
"person",
"benunit",
"household",
]
for dataset in required_datasets:
if dataset not in f:
raise ValueError(
f"Dataset '{dataset}' not found in the file: {file_path}"
)
def __init__(
self,
file_path: str = None,
person: pd.DataFrame = None,
benunit: pd.DataFrame = None,
household: pd.DataFrame = None,
fiscal_year: int = 2025,
):
if file_path is not None:
self.validate_file_path(file_path)
with pd.HDFStore(file_path) as f:
self.person = f["person"]
self.benunit = f["benunit"]
self.household = f["household"]
self.time_period = str(f["time_period"].iloc[0])
else:
if person is None or benunit is None or household is None:
raise ValueError(
"Must provide either a file path or all three DataFrames (person, benunit, household)."
)
self.person = person
self.benunit = benunit
self.household = household
self.time_period = str(fiscal_year)
self.data_format = "arrays"
self.tables = (self.person, self.benunit, self.household)
def save(self, file_path: str):
with pd.HDFStore(file_path) as f:
f.put("person", self.person, format="table", data_columns=True)
f.put("benunit", self.benunit, format="table", data_columns=True)
f.put(
"household", self.household, format="table", data_columns=True
)
f.put("time_period", pd.Series([self.time_period]), format="table")
def load(self):
data = {}
for df in (self.person, self.benunit, self.household):
for col in df.columns:
data[col] = df[col].values
return data
def copy(self):
return UKDataset(
person=self.person.copy(),
benunit=self.benunit.copy(),
household=self.household.copy(),
)
def validate(self):
# Check for NaNs in the tables
for df in self.tables:
for col in df.columns:
if df[col].isna().any():
raise ValueError(f"Column '{col}' contains NaN values.")
@staticmethod
def from_simulation(
simulation: "Microsimulation", fiscal_year: int = 2025
):
entity_dfs = {}
for entity in ["person", "benunit", "household"]:
input_variables = [
variable
for variable in simulation.input_variables
if simulation.tax_benefit_system.variables[variable].entity.key
== entity
]
entity_dfs[entity] = simulation.calculate_dataframe(
input_variables, period=fiscal_year
)
return UKDataset(
person=entity_dfs["person"],
benunit=entity_dfs["benunit"],
household=entity_dfs["household"],
fiscal_year=fiscal_year,
)