Skip to content

Commit 6166d55

Browse files
Merge pull request #43 from PolicyEngine/api-parity
Add all remaining general economy impacts
2 parents e21cb8d + 0d6e545 commit 6166d55

File tree

14 files changed

+909
-92
lines changed

14 files changed

+909
-92
lines changed

docs/schema.ipynb

Lines changed: 341 additions & 91 deletions
Large diffs are not rendered by default.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from policyengine import Simulation
2+
from microdf import MicroSeries
3+
4+
5+
def income(simulation: Simulation):
6+
baseline = simulation.calculate("macro/baseline")
7+
reform = simulation.calculate("macro/reform")
8+
9+
baseline_income = MicroSeries(
10+
baseline["household"]["finance"]["household_net_income"],
11+
weights=baseline["household"]["demographics"]["household_weight"],
12+
)
13+
reform_income = MicroSeries(
14+
reform["household"]["finance"]["household_net_income"],
15+
weights=baseline_income.weights,
16+
)
17+
18+
# Filter out negative decile values
19+
decile = MicroSeries(
20+
baseline["household"]["finance"]["household_income_decile"]
21+
)
22+
baseline_income_filtered = baseline_income[decile >= 0]
23+
reform_income_filtered = reform_income[decile >= 0]
24+
25+
income_change = reform_income_filtered - baseline_income_filtered
26+
rel_income_change_by_decile = (
27+
income_change.groupby(decile).sum()
28+
/ baseline_income_filtered.groupby(decile).sum()
29+
)
30+
31+
avg_income_change_by_decile = (
32+
income_change.groupby(decile).sum()
33+
/ baseline_income_filtered.groupby(decile).count()
34+
)
35+
rel_decile_dict = rel_income_change_by_decile.to_dict()
36+
avg_decile_dict = avg_income_change_by_decile.to_dict()
37+
result = dict(
38+
relative={int(k): v for k, v in rel_decile_dict.items()},
39+
average={int(k): v for k, v in avg_decile_dict.items()},
40+
)
41+
return result
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from policyengine import Simulation
2+
from microdf import MicroSeries
3+
4+
5+
def wealth(simulation: Simulation):
6+
if simulation.country != "uk":
7+
return {}
8+
9+
baseline = simulation.calculate("macro/baseline")
10+
reform = simulation.calculate("macro/reform")
11+
12+
baseline_income = MicroSeries(
13+
baseline["household"]["finance"]["household_net_income"],
14+
weights=baseline["household"]["demographics"]["household_weight"],
15+
)
16+
reform_income = MicroSeries(
17+
reform["household"]["finance"]["household_net_income"],
18+
weights=baseline_income.weights,
19+
)
20+
21+
# Filter out negative decile values
22+
decile = MicroSeries(baseline["household"]["finance"]["wealth_decile"])
23+
baseline_income_filtered = baseline_income[decile >= 0]
24+
reform_income_filtered = reform_income[decile >= 0]
25+
26+
income_change = reform_income_filtered - baseline_income_filtered
27+
rel_income_change_by_decile = (
28+
income_change.groupby(decile).sum()
29+
/ baseline_income_filtered.groupby(decile).sum()
30+
)
31+
32+
avg_income_change_by_decile = (
33+
income_change.groupby(decile).sum()
34+
/ baseline_income_filtered.groupby(decile).count()
35+
)
36+
rel_decile_dict = rel_income_change_by_decile.to_dict()
37+
avg_decile_dict = avg_income_change_by_decile.to_dict()
38+
result = dict(
39+
relative={int(k): v for k, v in rel_decile_dict.items()},
40+
average={int(k): v for k, v in avg_decile_dict.items()},
41+
)
42+
return result
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from policyengine import Simulation
2+
3+
4+
def detailed_budget(simulation: Simulation):
5+
baseline = simulation.calculate("macro/baseline")
6+
reform = simulation.calculate("macro/reform")
7+
result = {}
8+
if simulation.country == "uk":
9+
for program in baseline["gov"]["programs"]:
10+
# baseline[programs][program] = total budgetary impact of program
11+
result[program] = dict(
12+
baseline=baseline["gov"]["programs"][program],
13+
reform=reform["gov"]["programs"][program],
14+
difference=reform["gov"]["programs"][program]
15+
- baseline["gov"]["programs"][program],
16+
)
17+
return result
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from policyengine import Simulation
2+
3+
4+
def inequality(simulation: Simulation):
5+
baseline = simulation.calculate("macro/baseline")["household"][
6+
"inequality"
7+
]
8+
reform = simulation.calculate("macro/reform")["household"]["inequality"]
9+
10+
return dict(
11+
gini=dict(
12+
baseline=baseline["gini"],
13+
reform=reform["gini"],
14+
),
15+
top_10_pct_share=dict(
16+
baseline=baseline["top_10_percent_share"],
17+
reform=reform["top_10_percent_share"],
18+
),
19+
top_1_pct_share=dict(
20+
baseline=baseline["top_1_percent_share"],
21+
reform=reform["top_1_percent_share"],
22+
),
23+
)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
from policyengine import Simulation
2+
from microdf import MicroSeries
3+
import numpy as np
4+
5+
6+
def labor_supply_response(simulation: Simulation) -> dict:
7+
baseline = simulation.calculate("macro/baseline")
8+
reform = simulation.calculate("macro/reform")
9+
10+
substitution_lsr = (
11+
reform["household"]["labor_supply"]["substitution_lsr"]
12+
- baseline["household"]["labor_supply"]["substitution_lsr"]
13+
)
14+
income_lsr = (
15+
reform["household"]["labor_supply"]["income_lsr"]
16+
- baseline["household"]["labor_supply"]["income_lsr"]
17+
)
18+
total_change = substitution_lsr + income_lsr
19+
revenue_change = (
20+
reform["household"]["labor_supply"]["budgetary_impact_lsr"]
21+
- baseline["household"]["labor_supply"]["budgetary_impact_lsr"]
22+
)
23+
24+
substitution_lsr_hh = np.array(
25+
reform["household"]["labor_supply"]["substitution_lsr_hh"]
26+
) - np.array(baseline["household"]["labor_supply"]["substitution_lsr_hh"])
27+
income_lsr_hh = np.array(
28+
reform["household"]["labor_supply"]["income_lsr_hh"]
29+
) - np.array(baseline["household"]["labor_supply"]["income_lsr_hh"])
30+
decile = np.array(
31+
baseline["household"]["finance"]["household_income_decile"]
32+
)
33+
household_weight = baseline["household"]["demographics"][
34+
"household_weight"
35+
]
36+
37+
total_lsr_hh = substitution_lsr_hh + income_lsr_hh
38+
39+
emp_income = MicroSeries(
40+
baseline["household"]["finance"]["employment_income_hh"],
41+
weights=household_weight,
42+
)
43+
self_emp_income = MicroSeries(
44+
baseline["household"]["finance"]["self_employment_income_hh"],
45+
weights=household_weight,
46+
)
47+
earnings = emp_income + self_emp_income
48+
original_earnings = earnings - total_lsr_hh
49+
substitution_lsr_hh = MicroSeries(
50+
substitution_lsr_hh, weights=household_weight
51+
)
52+
income_lsr_hh = MicroSeries(income_lsr_hh, weights=household_weight)
53+
54+
decile_avg = dict(
55+
income=income_lsr_hh.groupby(decile).mean().to_dict(),
56+
substitution=substitution_lsr_hh.groupby(decile).mean().to_dict(),
57+
)
58+
decile_rel = dict(
59+
income=(
60+
income_lsr_hh.groupby(decile).sum()
61+
/ original_earnings.groupby(decile).sum()
62+
).to_dict(),
63+
substitution=(
64+
substitution_lsr_hh.groupby(decile).sum()
65+
/ original_earnings.groupby(decile).sum()
66+
).to_dict(),
67+
)
68+
69+
relative_lsr = dict(
70+
income=(income_lsr_hh.sum() / original_earnings.sum()),
71+
substitution=(substitution_lsr_hh.sum() / original_earnings.sum()),
72+
)
73+
74+
decile_rel["income"] = {
75+
int(k): v for k, v in decile_rel["income"].items() if k > 0
76+
}
77+
decile_rel["substitution"] = {
78+
int(k): v for k, v in decile_rel["substitution"].items() if k > 0
79+
}
80+
81+
hours = dict(
82+
baseline=baseline["household"]["labor_supply"]["weekly_hours"],
83+
reform=reform["household"]["labor_supply"]["weekly_hours"],
84+
change=reform["household"]["labor_supply"]["weekly_hours"]
85+
- baseline["household"]["labor_supply"]["weekly_hours"],
86+
income_effect=reform["household"]["labor_supply"][
87+
"weekly_hours_income_effect"
88+
]
89+
- baseline["household"]["labor_supply"]["weekly_hours_income_effect"],
90+
substitution_effect=reform["household"]["labor_supply"][
91+
"weekly_hours_substitution_effect"
92+
]
93+
- baseline["household"]["labor_supply"][
94+
"weekly_hours_substitution_effect"
95+
],
96+
)
97+
98+
return dict(
99+
substitution_lsr=substitution_lsr,
100+
income_lsr=income_lsr,
101+
relative_lsr=relative_lsr,
102+
total_change=total_change,
103+
revenue_change=revenue_change,
104+
decile=dict(
105+
average=decile_avg,
106+
relative=decile_rel,
107+
),
108+
hours=hours,
109+
)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from policyengine import Simulation
2+
from microdf import MicroSeries
3+
4+
5+
def age(simulation: Simulation):
6+
baseline = simulation.calculate("macro/baseline")["household"]["finance"]
7+
reform = simulation.calculate("macro/reform")["household"]["finance"]
8+
baseline_demographics = simulation.calculate("macro/baseline")[
9+
"household"
10+
]["demographics"]
11+
12+
baseline_poverty = MicroSeries(
13+
baseline["person_in_poverty"],
14+
weights=baseline_demographics["person_weight"],
15+
)
16+
baseline_deep_poverty = MicroSeries(
17+
baseline["person_in_deep_poverty"],
18+
weights=baseline_demographics["person_weight"],
19+
)
20+
reform_poverty = MicroSeries(
21+
reform["person_in_poverty"], weights=baseline_poverty.weights
22+
)
23+
reform_deep_poverty = MicroSeries(
24+
reform["person_in_deep_poverty"], weights=baseline_poverty.weights
25+
)
26+
age = MicroSeries(baseline_demographics["age"])
27+
28+
poverty = dict(
29+
child=dict(
30+
baseline=float(baseline_poverty[age < 18].mean()),
31+
reform=float(reform_poverty[age < 18].mean()),
32+
),
33+
adult=dict(
34+
baseline=float(baseline_poverty[(age >= 18) & (age < 65)].mean()),
35+
reform=float(reform_poverty[(age >= 18) & (age < 65)].mean()),
36+
),
37+
senior=dict(
38+
baseline=float(baseline_poverty[age >= 65].mean()),
39+
reform=float(reform_poverty[age >= 65].mean()),
40+
),
41+
all=dict(
42+
baseline=float(baseline_poverty.mean()),
43+
reform=float(reform_poverty.mean()),
44+
),
45+
)
46+
47+
deep_poverty = dict(
48+
child=dict(
49+
baseline=float(baseline_deep_poverty[age < 18].mean()),
50+
reform=float(reform_deep_poverty[age < 18].mean()),
51+
),
52+
adult=dict(
53+
baseline=float(
54+
baseline_deep_poverty[(age >= 18) & (age < 65)].mean()
55+
),
56+
reform=float(reform_deep_poverty[(age >= 18) & (age < 65)].mean()),
57+
),
58+
senior=dict(
59+
baseline=float(baseline_deep_poverty[age >= 65].mean()),
60+
reform=float(reform_deep_poverty[age >= 65].mean()),
61+
),
62+
all=dict(
63+
baseline=float(baseline_deep_poverty.mean()),
64+
reform=float(reform_deep_poverty.mean()),
65+
),
66+
)
67+
68+
return dict(
69+
poverty=poverty,
70+
deep_poverty=deep_poverty,
71+
)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from policyengine import Simulation
2+
from microdf import MicroSeries
3+
4+
5+
def gender(simulation: Simulation):
6+
baseline = simulation.calculate("macro/baseline")["household"]["finance"]
7+
reform = simulation.calculate("macro/reform")["household"]["finance"]
8+
baseline_demographics = simulation.calculate("macro/baseline")[
9+
"household"
10+
]["demographics"]
11+
12+
if baseline_demographics["is_male"] is None:
13+
return {}
14+
baseline_poverty = MicroSeries(
15+
baseline["person_in_poverty"],
16+
weights=baseline_demographics["person_weight"],
17+
)
18+
baseline_deep_poverty = MicroSeries(
19+
baseline["person_in_deep_poverty"],
20+
weights=baseline_demographics["person_weight"],
21+
)
22+
reform_poverty = MicroSeries(
23+
reform["person_in_poverty"], weights=baseline_poverty.weights
24+
)
25+
reform_deep_poverty = MicroSeries(
26+
reform["person_in_deep_poverty"], weights=baseline_poverty.weights
27+
)
28+
is_male = MicroSeries(baseline_demographics["is_male"])
29+
30+
poverty = dict(
31+
male=dict(
32+
baseline=float(baseline_poverty[is_male].mean()),
33+
reform=float(reform_poverty[is_male].mean()),
34+
),
35+
female=dict(
36+
baseline=float(baseline_poverty[~is_male].mean()),
37+
reform=float(reform_poverty[~is_male].mean()),
38+
),
39+
)
40+
41+
deep_poverty = dict(
42+
male=dict(
43+
baseline=float(baseline_deep_poverty[is_male].mean()),
44+
reform=float(reform_deep_poverty[is_male].mean()),
45+
),
46+
female=dict(
47+
baseline=float(baseline_deep_poverty[~is_male].mean()),
48+
reform=float(reform_deep_poverty[~is_male].mean()),
49+
),
50+
)
51+
52+
return dict(
53+
poverty=poverty,
54+
deep_poverty=deep_poverty,
55+
)

0 commit comments

Comments
 (0)