|
1 | 1 | import pandas as pd |
2 | | -from .soi import pe_to_soi, get_soi |
3 | 2 | import numpy as np |
| 3 | + |
4 | 4 | from policyengine_us_data.storage import STORAGE_FOLDER |
| 5 | +from policyengine_us_data.storage.pull_soi_state_targets import ( |
| 6 | + STATE_ABBR_TO_FIPS, |
| 7 | +) |
5 | 8 | from policyengine_core.reforms import Reform |
| 9 | +from policyengine_us_data.utils.soi import pe_to_soi, get_soi |
6 | 10 |
|
7 | 11 |
|
8 | 12 | def fmt(x): |
@@ -549,6 +553,10 @@ def build_loss_matrix(dataset: type, time_period): |
549 | 553 | loss_matrix, targets_array, sim |
550 | 554 | ) |
551 | 555 |
|
| 556 | + snap_state_target_names, snap_state_targets = _add_snap_state_targets(sim) |
| 557 | + targets_array.extend(snap_state_targets) |
| 558 | + loss_matrix = _add_snap_metric_columns(loss_matrix, sim) |
| 559 | + |
552 | 560 | return loss_matrix, np.array(targets_array) |
553 | 561 |
|
554 | 562 |
|
@@ -713,3 +721,75 @@ def _add_state_real_estate_taxes(loss_matrix, targets_list, sim): |
713 | 721 | loss_matrix[label] = real_estate_taxes * in_state |
714 | 722 |
|
715 | 723 | return targets_list, loss_matrix |
| 724 | + |
| 725 | + |
| 726 | +def _add_snap_state_targets(sim): |
| 727 | + """ |
| 728 | + Add snap targets at the state level, adjusted in aggregate to the sim |
| 729 | + """ |
| 730 | + snap_targets = pd.read_csv(STORAGE_FOLDER / "snap_state.csv") |
| 731 | + time_period = sim.default_calculation_period |
| 732 | + |
| 733 | + national_cost_target = sim.tax_benefit_system.parameters( |
| 734 | + time_period |
| 735 | + ).calibration.gov.cbo._children["snap"] |
| 736 | + ratio = snap_targets[["Cost"]].sum().values[0] / national_cost_target |
| 737 | + snap_targets[["CostAdj"]] = snap_targets[["Cost"]] / ratio |
| 738 | + assert ( |
| 739 | + np.round(snap_targets[["CostAdj"]].sum().values[0]) |
| 740 | + == national_cost_target |
| 741 | + ) |
| 742 | + |
| 743 | + cost_targets = snap_targets.copy()[["GEO_ID", "CostAdj"]] |
| 744 | + cost_targets["target_name"] = ( |
| 745 | + cost_targets["GEO_ID"].str[-4:] + "/snap-cost" |
| 746 | + ) |
| 747 | + |
| 748 | + hh_targets = snap_targets.copy()[["GEO_ID", "Households"]] |
| 749 | + hh_targets["target_name"] = snap_targets["GEO_ID"].str[-4:] + "/snap-hhs" |
| 750 | + |
| 751 | + target_names = ( |
| 752 | + cost_targets["target_name"].tolist() |
| 753 | + + hh_targets["target_name"].tolist() |
| 754 | + ) |
| 755 | + target_values = ( |
| 756 | + cost_targets["CostAdj"].astype(float).tolist() |
| 757 | + + hh_targets["Households"].astype(float).tolist() |
| 758 | + ) |
| 759 | + return target_names, target_values |
| 760 | + |
| 761 | + |
| 762 | +def _add_snap_metric_columns( |
| 763 | + loss_matrix: pd.DataFrame, |
| 764 | + sim, |
| 765 | +): |
| 766 | + """ |
| 767 | + Add SNAP metric columns to the loss_matrix. |
| 768 | + """ |
| 769 | + snap_targets = pd.read_csv(STORAGE_FOLDER / "snap_state.csv") |
| 770 | + |
| 771 | + snap_cost = sim.calculate("snap_reported", map_to="household").values |
| 772 | + snap_hhs = ( |
| 773 | + sim.calculate("snap_reported", map_to="household").values > 0 |
| 774 | + ).astype(int) |
| 775 | + |
| 776 | + state = sim.calculate("state_code", map_to="person").values |
| 777 | + state = sim.map_result( |
| 778 | + state, "person", "household", how="value_from_first_person" |
| 779 | + ) |
| 780 | + STATE_ABBR_TO_FIPS["DC"] = 11 |
| 781 | + state_fips = pd.Series(state).apply(lambda s: STATE_ABBR_TO_FIPS[s]) |
| 782 | + |
| 783 | + for _, r in snap_targets.iterrows(): |
| 784 | + in_state = state_fips == r.GEO_ID[-2:] |
| 785 | + metric = np.where(in_state, snap_cost, 0.0) |
| 786 | + col_name = f"{r.GEO_ID[-4:]}/snap-cost" |
| 787 | + loss_matrix[col_name] = metric |
| 788 | + |
| 789 | + for _, r in snap_targets.iterrows(): |
| 790 | + in_state = state_fips == r.GEO_ID[-2:] |
| 791 | + metric = np.where(in_state, snap_hhs, 0.0) |
| 792 | + col_name = f"{r.GEO_ID[-4:]}/snap-hhs" |
| 793 | + loss_matrix[col_name] = metric |
| 794 | + |
| 795 | + return loss_matrix |
0 commit comments