Skip to content

Commit 3f00617

Browse files
Merge pull request #255 from PolicyEngine/fix-negetive-income
Fix negative income values
2 parents b8a1d83 + 0ac74c2 commit 3f00617

3 files changed

Lines changed: 42 additions & 8 deletions

File tree

changelog_entry.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- bump: patch
2+
changes:
3+
fixed:
4+
- Clip negative values to zero for employment, self-employment, savings interest, tax-free savings, and dividend income variables.

policyengine_uk_data/datasets/frs.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,9 @@ def determine_education_level(fted_val, typeed2_val, age_val):
339339

340340
WEEKS_IN_YEAR = 365.25 / 7
341341

342-
pe_person["employment_income"] = person.inearns * WEEKS_IN_YEAR
342+
pe_person["employment_income"] = (
343+
np.maximum(0, person.inearns) * WEEKS_IN_YEAR
344+
)
343345

344346
pension_payment = sum_to_entity(
345347
pension.penpay * (pension.penpay > 0),
@@ -365,17 +367,20 @@ def determine_education_level(fted_val, typeed2_val, age_val):
365367
pension_payment + pension_tax_paid + pension_deductions_removed
366368
) * WEEKS_IN_YEAR
367369

368-
pe_person["self_employment_income"] = person.seincam2 * WEEKS_IN_YEAR
370+
pe_person["self_employment_income"] = (
371+
np.maximum(0, person.seincam2) * WEEKS_IN_YEAR
372+
)
369373

370374
INVERTED_BASIC_RATE = 1.25
371375

372-
pe_person["tax_free_savings_income"] = (
376+
pe_person["tax_free_savings_income"] = np.maximum(
377+
0,
373378
sum_to_entity(
374379
account.accint * (account.account == 21),
375380
account.person_id,
376381
person.person_id,
377382
)
378-
* WEEKS_IN_YEAR
383+
* WEEKS_IN_YEAR,
379384
)
380385
taxable_savings_interest = (
381386
sum_to_entity(
@@ -389,10 +394,12 @@ def determine_education_level(fted_val, typeed2_val, age_val):
389394
)
390395
* WEEKS_IN_YEAR
391396
)
392-
pe_person["savings_interest_income"] = (
393-
taxable_savings_interest + pe_person["tax_free_savings_income"].values
397+
pe_person["savings_interest_income"] = np.maximum(
398+
0,
399+
taxable_savings_interest + pe_person["tax_free_savings_income"].values,
394400
)
395-
pe_person["dividend_income"] = (
401+
pe_person["dividend_income"] = np.maximum(
402+
0,
396403
sum_to_entity(
397404
(
398405
account.accint
@@ -405,7 +412,7 @@ def determine_education_level(fted_val, typeed2_val, age_val):
405412
account.person_id,
406413
person.index,
407414
)
408-
* 52
415+
* 52,
409416
)
410417
is_head = person.hrpid == 1
411418
household_property_income = (
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
3+
INCOME_VARIABLES = [
4+
"employment_income",
5+
"self_employment_income",
6+
"tax_free_savings_income",
7+
"savings_interest_income",
8+
"dividend_income",
9+
"private_pension_income",
10+
"property_income",
11+
"maintenance_income",
12+
"miscellaneous_income",
13+
]
14+
15+
16+
@pytest.mark.parametrize("variable", INCOME_VARIABLES)
17+
def test_income_non_negative(frs, variable: str):
18+
"""Test that income variables have no negative values."""
19+
values = frs.person[variable]
20+
min_value = values.min()
21+
assert (
22+
min_value >= 0
23+
), f"{variable} has negative values (min = {min_value:.2f})"

0 commit comments

Comments
 (0)