Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ releases are available on [Anaconda.org](https://anaconda.org/conda-forge/gettsi

## Unpublished

- {gh}`772` Add Mindesteinkommen check to Wohngeld, calculate anz_eig_kind_bis_24
- {gh}`778` Endogenous calculation of `bg_id` and `wthh_id` if there is at most one
Familiengemeinschaft in the household ({ghuser}`MImmesberger`, {ghuser}`hmgaudecker`).
- {gh}`777` Add Mindesteinkommen check to Wohngeld, calculate anz_eig_kind_bis_24
instead of requiring it as an input variable ({ghuser}`MImmesberger`).
- {gh}`771` Move SGB II Regelsatz calculation from BG to individual level
({ghuser}`MImmesberger`).
Expand Down
4 changes: 1 addition & 3 deletions docs/geps/gep-01.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,7 @@ GETTSIM knows about the following units:
- `hh_id`: Haushalt, individuals living together in a household in the Wohngeld sense
(§5 WoGG).
- `wthh_id`: Wohngeldrechtlicher Teilhaushalt, i.e. members of a household for whom the
priority check for Wohngeld/ALG2 yields the same result ∈ {True, False}. This unit is
based on the priority check via `wohngeld_vorrang_bg` and
`wohngeld_kinderzuschl_vorrang_bg`.
priority check for Wohngeld/ALG2 yields the same result ∈ {True, False}.
- `fg_id`: Familiengemeinschaft. Maximum of two generations, the relevant unit for
Bürgergeld / Arbeitslosengeld 2. Another way to think about this is the potential
Bedarfsgemeinschaft before making checks for whether children have enough income fend
Expand Down
9 changes: 9 additions & 0 deletions docs/gettsim_objects/input_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ Identifier of person that claims Kindergeld for the particular child

Type: int

(beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2)=

## \`beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2\`\`

Individual may have claim on Wohngeld and Kinderzuschlag instead of Arbeitslosengeld II
/ Bürgergeld

Type: bool

(wohnort_ost)=

## `wohnort_ost`
Expand Down
16 changes: 6 additions & 10 deletions docs/tutorials/policy_functions.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,17 @@
"outputs": [],
"source": [
"def arbeitsl_geld_2_m_bg(\n",
" arbeitsl_geld_2_vor_vorrang_m_bg,\n",
" # wohngeld_vorrang_bg,\n",
" # kinderzuschl_vorrang_bg,\n",
" # wohngeld_kinderzuschl_vorrang_bg,\n",
" arbeitsl_geld_2_anspruchshöhe_m_bg,\n",
" # beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_bg,\n",
" erwachsene_alle_rentner_hh,\n",
"):\n",
" if (\n",
" # wohngeld_vorrang_bg\n",
" # | kinderzuschl_vorrang_bg\n",
" # | wohngeld_kinderzuschl_vorrang_bg\n",
" erwachsene_alle_rentner_hh\n",
" # (not beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_bg) and\n",
" not erwachsene_alle_rentner_hh\n",
" ):\n",
" out = 0.0\n",
" out = arbeitsl_geld_2_anspruchshöhe_m_bg\n",
" else:\n",
" out = arbeitsl_geld_2_vor_vorrang_m_bg\n",
" out = 0.0\n",
"\n",
" return out"
]
Expand Down
2 changes: 1 addition & 1 deletion src/_gettsim/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def set_array_backend(backend: str):
"p_id_ehepartner": int,
"p_id_einstandspartner": int,
"vermögen_bedürft": float,
"eigenbedarf_gedeckt": bool,
"beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2": bool,
"gemeinsam_veranlagt": bool,
"bruttolohn_m": float,
"alter": int,
Expand Down
40 changes: 40 additions & 0 deletions src/_gettsim/demographic_vars.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import numpy

from _gettsim.config import SUPPORTED_GROUPINGS
from _gettsim.shared import join_numpy, policy_info

aggregate_by_p_id_demographic_vars = {
"ges_pflegev_anz_kinder_bis_24_elternteil_1": {
Expand Down Expand Up @@ -175,6 +176,45 @@ def erwachsen(kind: bool) -> bool:
return out


@policy_info(skip_vectorization=True)
def ist_kind_in_fg(
p_id: numpy.ndarray[int],
fg_id: numpy.ndarray[int],
p_id_elternteil_1: numpy.ndarray[int],
p_id_elternteil_2: numpy.ndarray[int],
) -> numpy.ndarray[bool]:
"""Person is a child in the Familiengemeinschaft.

Parameters
----------
p_id
See basic input variable :ref:`p_id <p_id>`.
fg_id
See :func:`fg_id`.
p_id_elternteil_1
See basic input variable :ref:`p_id_elternteil_1 <p_id_elternteil_1>`.
p_id_elternteil_2
See basic input variable :ref:`p_id_elternteil_2 <p_id_elternteil_2>`.

Returns
-------
"""
fg_id_elternteil_1 = join_numpy(
p_id_elternteil_1,
p_id,
fg_id,
value_if_foreign_key_is_missing=-1,
)
fg_id_elternteil_2 = join_numpy(
p_id_elternteil_2,
p_id,
fg_id,
value_if_foreign_key_is_missing=-1,
)

return (fg_id_elternteil_1 == fg_id) | (fg_id_elternteil_2 == fg_id)


def erwachsene_alle_rentner_hh(anz_erwachsene_hh: int, anz_rentner_hh: int) -> bool:
"""Calculate if all adults in the household are pensioners.

Expand Down
115 changes: 103 additions & 12 deletions src/_gettsim/groupings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,61 @@
def create_groupings() -> dict[str, Callable]:
return {
"wthh_id": wthh_id_numpy,
"wthh_id_endogen": wthh_id_endogen_numpy,
"fg_id": fg_id_numpy,
"bg_id": bg_id_numpy,
"bg_id_endogen": bg_id_endogen_numpy,
"eg_id": eg_id_numpy,
"ehe_id": ehe_id_numpy,
"sn_id": sn_id_numpy,
}


def bg_id_numpy(
hh_id: numpy.ndarray[int],
fg_id: numpy.ndarray[int],
alter: numpy.ndarray[int],
eigenbedarf_gedeckt: numpy.ndarray[bool],
arbeitsl_geld_2_ist_kind_und_eigenbedarf_gedeckt: numpy.ndarray[bool],
) -> numpy.ndarray[int]:
"""
ID of Bedarfsgemeinschaften.

If not overwritten by user-provided bg_ids, all children who cover their needs are
separated from the parental Bedarfsgemeinschaft.
"""
_fail_if_more_than_one_fg_in_hh(hh_id, fg_id)

counter = Counter()
result = []

for index, current_fg_id in enumerate(fg_id):
if arbeitsl_geld_2_ist_kind_und_eigenbedarf_gedeckt[index]:
counter[current_fg_id] += 1
result.append(current_fg_id * 100 + counter[current_fg_id])
else:
result.append(current_fg_id * 100)

return numpy.asarray(result)


def bg_id_endogen_numpy(
fg_id: numpy.ndarray[int],
alle_beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_fg: numpy.ndarray[bool],
ist_kind_in_fg: numpy.ndarray[bool],
beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_endogen: numpy.ndarray[bool],
) -> numpy.ndarray[int]:
"""
Compute the ID of the Bedarfsgemeinschaft for each person.
Compute the ID of the Bedarfsgemeinschaft endogenously for each person.
"""
counter = Counter()
result = []

for index, current_fg_id in enumerate(fg_id):
current_alter = alter[index]
current_eigenbedarf_gedeckt = eigenbedarf_gedeckt[index]
# TODO(@MImmesberger): Remove hard-coded number
# https://github.com/iza-institute-of-labor-economics/gettsim/issues/668
if current_alter < 25 and current_eigenbedarf_gedeckt:
current_wog_kiz_statt_alg_2 = (
beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_endogen[index]
)
if alle_beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_fg[index]:
result.append(current_fg_id * 100)
elif ist_kind_in_fg[index] and current_wog_kiz_statt_alg_2:
counter[current_fg_id] += 1
result.append(current_fg_id * 100 + counter[current_fg_id])
else:
Expand Down Expand Up @@ -216,17 +246,78 @@ def sn_id_numpy(

def wthh_id_numpy(
hh_id: numpy.ndarray[int],
wohngeld_vorrang_bg: numpy.ndarray[bool],
wohngeld_kinderzuschl_vorrang_bg: numpy.ndarray[bool],
fg_id: numpy.ndarray[int],
arbeitsl_geld_2_ist_kind_und_eigenbedarf_gedeckt: numpy.ndarray[bool],
) -> numpy.ndarray[int]:
"""
Compute the ID of the wohngeldrechtlicher Teilhaushalt.
ID of the wohngeldrechtlicher Teilhaushalt.

If not overwritten by user-provided wthh_ids, children who cover their needs are in
the Wohngeld wthh and parents and children who do not cover their needs are in the
Arbeitslosengeld II / Bürgergeld wthh.
"""
_fail_if_more_than_one_fg_in_hh(hh_id, fg_id)

result = []
# Create candidate wthh_ids
for index, current_hh_id in enumerate(hh_id):
if wohngeld_vorrang_bg[index] or wohngeld_kinderzuschl_vorrang_bg[index]:
# Put children with covered needs in the Wohngeld wthh
if arbeitsl_geld_2_ist_kind_und_eigenbedarf_gedeckt[index]:
result.append(current_hh_id * 100 + 1)
# Parents and children who do not cover needs in ALG II wthh
else:
result.append(current_hh_id * 100)

return numpy.asarray(result)


def wthh_id_endogen_numpy(
hh_id: numpy.ndarray[int],
beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_endogen: numpy.ndarray[bool],
) -> numpy.ndarray[int]:
"""
Compute the ID of the wohngeldrechtlicher Teilhaushalt endogenously.
"""
result = []
for index, current_hh_id in enumerate(hh_id):
if beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2_endogen[index]:
result.append(current_hh_id * 100 + 1)
else:
result.append(current_hh_id * 100)

return numpy.asarray(result)


def _fail_if_more_than_one_fg_in_hh(
hh_id: numpy.ndarray[int],
fg_id: numpy.ndarray[int],
):
"""
Fail if there is more than one `fg_id` in a household.

GETTSIM does not support the endogenous creation of Bedarfsgemeinschaften in this
case. The user has to provide `bg_id`, `wthh_id` and
`beantragt_wohngeld_kinderzuschl_statt_arbeitsl_geld_2` themselves.

Parameters
----------
hh_id : numpy.ndarray[int]
Array of household IDs.
fg_id : numpy.ndarray[int]
Array of family group IDs.
"""
unique_hh_ids = numpy.unique(hh_id)
hh_ids_with_multiple_fgs_list = []
for this_hh_id in unique_hh_ids:
# Find all family group IDs for the current household ID
fg_ids_in_hh = fg_id[hh_id == this_hh_id]
if len(numpy.unique(fg_ids_in_hh)) > 1:
hh_ids_with_multiple_fgs_list.append(this_hh_id)
hh_ids_with_multiple_fgs = set(hh_ids_with_multiple_fgs_list)
error_msg = (
"There are households with more than one `fg_id`. GETTSIM does not support the "
"endogenous creation of Bedarfsgemeinschaften in this case yet. Please provide "
"`bg_id` and `wthh_id` yourself for the following households: "
f"{hh_ids_with_multiple_fgs}."
)
assert len(hh_ids_with_multiple_fgs) == 0, error_msg
2 changes: 1 addition & 1 deletion src/_gettsim/parameters/wohngeld.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1970,7 +1970,7 @@ klimakomponente_m:
5: 39.20
jede_weitere_person: 4.8
rounding:
wohngeld_anspruchshöhe_m_bg:
wohngeld_anspruchshöhe_m_fg:
1970-01-01:
base: 1
direction: nearest
Expand Down
1 change: 0 additions & 1 deletion src/_gettsim/synthetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ def create_constant_across_households_variables(df, n_adults, n_children, policy
"gemeinsam_veranlagt": (
df["kind"] == False if n_adults == 2 else False # noqa: E712
),
"eigenbedarf_gedeckt": False,
"mietstufe": 3,
"geburtsmonat": 1,
"geburtstag": 1,
Expand Down
Loading