User Guide¶
The Euromod Conector is a Python library providing tools for running simulations and interacting with the tax-benefit microsimulation model EUROMOD.
Installation¶
The Euromod Connector can be installed from PyPi using pip:
$ pip install euromod
Requirements¶
In order to run the model, we require two components: 1) the model (coded policy rules), and 2) the input microdata with the variables that respect the EUROMOD naming conventions. For more information, please, read the sections “Model” and “Input microdata” on the Download Euromod web page.
Running and navigating the model¶
The euromod package is object oriented and evolves around using the Model class that loads a representation of the EUROMOD model. Creating a euromod object works as follows
from euromod import Model
Create an object of the core.Model class by passing the path to the EUROMOD project:
mod=Model(r"C:\Users\serruha\Downloads\EUROMOD_RELEASES_J0.1+\EUROMOD_RELEASES_J0.1+")
mod
------------------------------
Model
------------------------------
countries: 28 elements
extensions: 12 elements
model_path: 'C:\\Users\\serruha\\Downloads\\EUROMOD_RELEASES_J0.1+\\EUROMOD_RELEASES_J0.1+'
Note that every object that is related to the EUROMOD project comes with an informative description. Here we can see that the model has 3 relevant attributes to the user:
countries
extensions
model_path
The countries and extensions attributes say that they contain elements. If we take a look at countries
mod.countriesies
The Model.countries attirbute is a container storing the core.Country objects which nest the country-specific tax-benefit policies and systems.
Displays the EUROMOD default countries:
mod.countries
0: AT
1: BE
2: BG
3: CY
4: CZ
5: DE
6: DK
7: EE
8: EL
9: ES
10: FI
11: FR
12: HR
13: HU
14: IE
15: IT
16: LT
17: LU
18: LV
19: MT
20: NL
21: PL
22: PT
23: RO
24: SE
25: SI
26: SK
27: SL
Displaying a specific country model, e.g. Simpleland, using the two-letters country code index:
We see indeed that the euromod model contains 28 countries. In a similar fashion we could have looked what kind of extensions that are stored in the model. The countries container can be indexed by both the number of the element and the country shortcode. Let us take a look at Sweden.
mod.countries["SE"]
------------------------------
Country
------------------------------
ct_factors: 271 elements
datasets: 36 elements
extensions: 13 elements
local_extensions: COVID
name: 'SE'
policies: 28 elements
systems: 19 elements
upratefactors: 25 elements
Here we see again an informative representation of the Country object, which contains several attributes that can be accessed. In order to simulate a system we run a specific System. We can obtain the system Container of the Country Sweden
mod.countries["SE"].systems
0: SE_2006
1: SE_2007
2: SE_2008
3: SE_2009
4: SE_2010
5: SE_2011
6: SE_2012
7: SE_2013
8: SE_2014
9: SE_2015
10: SE_2016
11: SE_2017
12: SE_2018
13: SE_2019
14: SE_2020
15: SE_2021
16: SE_2022
17: SE_2023
18: SE_2024
Running a simulation¶
In order to run the tax system we need a dataset that fits the requirement to use.In case you already know which dataset you want to use one can simply load the data and run the model as follows:.
import pandas as pd
data=pd.read_csv(r"C:\Users\serruha\DATA\2022 datasets\SE_2022_b1.txt",sep="\t")
out_baseline = mod.countries["SE"].systems["SE_2021"].run(data,"SE_2022_b1")
out_baseline
Simulation for system SE_2021 with dataset SE_2022_b1 finished.
------------------------------
Simulation
------------------------------
constantsToOverwrite: {}
errors: []
output_filenames: ['se_2021_std.txt']
outputs: Pandas DataFrame of 245 variables and 20448 observations.
Note that the run function here takes the mandatory argument dataset_id, which in our case is here SE_2022_b1. This is necessary such that EUROMOD can apply the dataset specific logic with respect to setting default values and uprating. This returned us a Simulation object with multiple attributes returned. The one of interest here is outputs, which contains the outputdataset(s) returned by the microsimulation model.
out_baseline.outputs[0]
| idhh | idperson | idmother | idfather | idpartner | idorighh | idorigperson | dag | dgn | dec | ... | il_means_bhope_prel_64 | il_means_bsa | il_means_bhope | tpr | tis | tad | tu_bho_se_HeadID | tu_bho_se_IsDependentChild | tu_bho_se_IsLoneParent | tu_bho_se_IsPartner | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 4416800.0 | 441680001.0 | 0.0 | 0.0 | 0.0 | 4416800.0 | 441680001.0 | 80.0 | 0.0 | 0.0 | ... | 463.630000 | 14776.555530 | 463.630000 | 0.0000 | 1267.58330 | 0.0 | 441680001.0 | 0.0 | 0.0 | 0.0 |
| 1 | 4416900.0 | 441690001.0 | 0.0 | 0.0 | 0.0 | 4416900.0 | 441690001.0 | 80.0 | 0.0 | 0.0 | ... | 10038.289690 | 16452.412536 | 10038.289690 | 0.0000 | 3647.33330 | 0.0 | 441690001.0 | 0.0 | 0.0 | 0.0 |
| 2 | 4419200.0 | 441920001.0 | 0.0 | 0.0 | 441920002.0 | 4419200.0 | 441920001.0 | 80.0 | 0.0 | 0.0 | ... | 6542.205003 | 12552.193817 | 6542.205003 | 0.0000 | 6959.58330 | 0.0 | 441920001.0 | 0.0 | 0.0 | 0.0 |
| 3 | 4419200.0 | 441920002.0 | 0.0 | 0.0 | 441920001.0 | 4419200.0 | 441920002.0 | 80.0 | 1.0 | 0.0 | ... | 11688.825003 | 16552.940678 | 11688.825003 | 0.0000 | 0.00000 | 0.0 | 441920001.0 | 0.0 | 0.0 | 1.0 |
| 4 | 4419800.0 | 441980001.0 | 0.0 | 0.0 | 0.0 | 4419800.0 | 441980001.0 | 80.0 | 1.0 | 0.0 | ... | 6022.705000 | 14296.703273 | 6022.705000 | 0.0000 | 2909.83330 | 0.0 | 441980001.0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 20443 | 7172700.0 | 717270004.0 | 0.0 | 0.0 | 0.0 | 7172700.0 | 717270004.0 | 18.0 | 1.0 | 4.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.0000 | 0.00000 | 0.0 | 717270002.0 | 1.0 | 0.0 | 0.0 |
| 20444 | 7172800.0 | 717280001.0 | 0.0 | 0.0 | 0.0 | 7172800.0 | 717280001.0 | 19.0 | 0.0 | 3.0 | ... | 1454.750000 | 6289.899870 | 3988.800000 | 0.0000 | 448.16667 | 0.0 | 717280001.0 | 0.0 | 0.0 | 0.0 |
| 20445 | 7173200.0 | 717320001.0 | 0.0 | 0.0 | 0.0 | 7173200.0 | 717320001.0 | 19.0 | 0.0 | 0.0 | ... | 0.000000 | 0.000000 | 0.000000 | 0.0000 | 22617.25000 | 0.0 | 717320001.0 | 0.0 | 0.0 | 0.0 |
| 20446 | 7173200.0 | 717320002.0 | 0.0 | 0.0 | 0.0 | 7173200.0 | 717320002.0 | 58.0 | 0.0 | 0.0 | ... | 1170.856663 | 32469.682515 | 22456.858163 | 0.0000 | 0.00000 | 0.0 | 717320002.0 | 0.0 | 0.0 | 0.0 |
| 20447 | 7173200.0 | 717320003.0 | 0.0 | 0.0 | 0.0 | 7173200.0 | 717320003.0 | 56.0 | 1.0 | 0.0 | ... | 0.000000 | 33969.753362 | 24636.833500 | 1600.5833 | 0.00000 | 0.0 | 717320003.0 | 0.0 | 0.0 | 0.0 |
20448 rows × 245 columns
Navigating the model¶
The Model object actually contains a full representation of the model that can be accessed using it’s attributes. The implementation in Python mimicks the hierarchical structure of the EUROMOD User Interface. A full description of the available types can be found in the API reference.
The spine¶
The spine of EUROMOD is what represents the series of calculations with respect taxes and benefits. The spine consists out of three hierarchically ordered elements:
Policy
Function
Parameter
The connector mimmicks this hierarchical implementation through an object-oriented representation. The three hierarchical elements are defined on the Country level and implemented on the System level.
Let us take a look at the policies, which are an attribute of the Country object.
mod.countries["SE"].policies
0: setdefault_se | | DEF: SET DEFAULT
1: uprate_se | | DEF: UPRATING FACTORS
2: ConstDef_se | | DEF: CONSTANTS
3: IlsDef_se | | DEF: INCOME CONCEPTS (standardized)
4: IlsUDBdef_se | | DEF: INCOME CONCEPTS (UDB)
5: ildef_se | | DEF: INCOME CONCEPTS (non-standardized)
6: random_se | | DEF: Random assignment
7: TransLMA_se | | DEF: Modelling labour market transitions (DO NOT S ...
8: tudef_se | | DEF: ASSESSMENT UNITS
9: yem_se | (with switch set for MWA) | DEF: minimum wage
10: neg_se | | DEF: recode negative self-employment income to zer ...
11: yemcomp_se | | BEN: wage compensation scheme COVID-19 (ONLY WORK ...
12: hhot_switch_se | (with switch set for HHoT_un, WEB) | DEF: switch on bunct for HHoT extension
13: bunct_se | | BEN: unemployment benefit (contributory)
14: bfapl_se | (with switch set for PBE) | BEN: Parental leave benefit
15: bpa_se | (with switch set for PBE) | BEN: Special leave days other parent (10 days)
16: tscee_se | | SIC: Employee Social Insurance contribution
17: tscer_se | | SIC: Employer Social Insurance contribution
18: tscse_se | | SIC: Self-employed Social Insurance contribution
19: tin_se | | TAX: Personal Income tax
20: tinkt_se | | TAX: Tax on Capital Income
21: bch_se | | BEN: Child benefit
22: bho_se | | BEN: Housing allowance
23: bhope_se | | BEN: Housing allowance for pensioners
24: bsamt_se | | BEN: Social Assistance (means-tested)
25: tco_se | | TAX: Commodities
26: output_std_se | | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
27: output_std_hh_se | | DEF: STANDARD OUTPUT HOUSEHOLD LEVEL
As one can see the policies attribute is a Container object here, and it’s elements which are of the type Policy here are accessible.
mod.countries["SE"].policies[22]
------------------------------
Policy
------------------------------
ID: '6B7D3970-7A4E-4BAC-BBB1-43ABBD3C989A'
comment: 'BEN: Housing allowance'
extensions: 0 elements
functions: 18 elements
name: 'bho_se'
order: '23'
private: 'no'
spineOrder: '23'
system_elements: 0 elements
The implementation of a policy is accessible through the System object.
mod.countries["SE"].systems["SE_2021"].policies
0: setdefault_se | on | DEF: SET DEFAULT
1: uprate_se | on | DEF: UPRATING FACTORS
2: ConstDef_se | on | DEF: CONSTANTS
3: IlsDef_se | on | DEF: INCOME CONCEPTS (standardized)
4: IlsUDBdef_se | on | DEF: INCOME CONCEPTS (UDB)
5: ildef_se | on | DEF: INCOME CONCEPTS (non-standardized)
6: random_se | on | DEF: Random assignment
7: TransLMA_se | off | DEF: Modelling labour market transitions (DO NOT S ...
8: tudef_se | on | DEF: ASSESSMENT UNITS
9: yem_se | off (with switch set for MWA) | DEF: minimum wage
10: neg_se | on | DEF: recode negative self-employment income to zer ...
11: yemcomp_se | on | BEN: wage compensation scheme COVID-19 (ONLY WORK ...
12: hhot_switch_se | on (with switch set for HHoT_un, WEB) | DEF: switch on bunct for HHoT extension
13: bunct_se | off | BEN: unemployment benefit (contributory)
14: bfapl_se | off (with switch set for PBE) | BEN: Parental leave benefit
15: bpa_se | off (with switch set for PBE) | BEN: Special leave days other parent (10 days)
16: tscee_se | on | SIC: Employee Social Insurance contribution
17: tscer_se | on | SIC: Employer Social Insurance contribution
18: tscse_se | on | SIC: Self-employed Social Insurance contribution
19: tin_se | on | TAX: Personal Income tax
20: tinkt_se | on | TAX: Tax on Capital Income
21: bch_se | on | BEN: Child benefit
22: bho_se | on | BEN: Housing allowance
23: bhope_se | on | BEN: Housing allowance for pensioners
24: bsamt_se | on | BEN: Social Assistance (means-tested)
25: tco_se | off | TAX: Commodities
26: output_std_se | on | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
27: output_std_hh_se | off | DEF: STANDARD OUTPUT HOUSEHOLD LEVEL
Here we see that some policies are turned off by default. Note that the behaviour of the policies can be controlled from the connector. We can for example switch the policy bunct_se to on. Let us first look at the policy
mod.countries["SE"].systems["SE_2021"].policies[22]
------------------------------
PolicyInSystem
------------------------------
ID: 'bde78132-3f44-4d2e-a1ea-4849f88c27766B7D3970-7A4E-4BAC-BBB1-43ABBD3C989A'
comment: 'BEN: Housing allowance'
extensions: 0 elements
functions: 18 elements
name: 'bho_se'
order: '23'
polID: '6B7D3970-7A4E-4BAC-BBB1-43ABBD3C989A'
private: 'no'
spineOrder: '23'
switch: 'on'
sysID: 'bde78132-3f44-4d2e-a1ea-4849f88c2776'
We see here that there is this attribute switch that is part of the PolicyInSystem class. This attribute, similar to attribute is modifiable and the changes that you will make will be passed to the EUROMOD software when simulating. Changes implemented during your Python session are however not lasting. For now, when making lasting changes to the model, one should implement them via the User Interface of EUROMOD. Note that the python connector is not checking what kind of modifications you make to the model. Changing attributes like ID’s are definitely not adviseable.
mod.countries["SE"].systems["SE_2021"].policies[13].switch = 'on'
out_with_bunct_se = mod.countries["SE"].systems["SE_2021"].run(data,"SE_2022_b1")
# Here we see that the average benefit, which is represented by ils_ben, is indeed larger by switching on the bunct_se policy.
out_baseline.outputs[0].ils_ben.mean() - out_with_bunct_se.outputs[0].ils_ben.mean()
Simulation for system SE_2021 with dataset SE_2022_b1 finished.
-10.688592026232982
mod.countries["SE"].systems["SE_2021"].policies
0: setdefault_se | on | DEF: SET DEFAULT
1: uprate_se | on | DEF: UPRATING FACTORS
2: ConstDef_se | on | DEF: CONSTANTS
3: IlsDef_se | on | DEF: INCOME CONCEPTS (standardized)
4: IlsUDBdef_se | on | DEF: INCOME CONCEPTS (UDB)
5: ildef_se | on | DEF: INCOME CONCEPTS (non-standardized)
6: random_se | on | DEF: Random assignment
7: TransLMA_se | off | DEF: Modelling labour market transitions (DO NOT S ...
8: tudef_se | on | DEF: ASSESSMENT UNITS
9: yem_se | off (with switch set for MWA) | DEF: minimum wage
10: neg_se | on | DEF: recode negative self-employment income to zer ...
11: yemcomp_se | on | BEN: wage compensation scheme COVID-19 (ONLY WORK ...
12: hhot_switch_se | on (with switch set for HHoT_un, WEB) | DEF: switch on bunct for HHoT extension
13: bunct_se | on | BEN: unemployment benefit (contributory)
14: bfapl_se | off (with switch set for PBE) | BEN: Parental leave benefit
15: bpa_se | off (with switch set for PBE) | BEN: Special leave days other parent (10 days)
16: tscee_se | on | SIC: Employee Social Insurance contribution
17: tscer_se | on | SIC: Employer Social Insurance contribution
18: tscse_se | on | SIC: Self-employed Social Insurance contribution
19: tin_se | on | TAX: Personal Income tax
20: tinkt_se | on | TAX: Tax on Capital Income
21: bch_se | on | BEN: Child benefit
22: bho_se | on | BEN: Housing allowance
23: bhope_se | on | BEN: Housing allowance for pensioners
24: bsamt_se | on | BEN: Social Assistance (means-tested)
25: tco_se | off | TAX: Commodities
26: output_std_se | on | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
27: output_std_hh_se | off | DEF: STANDARD OUTPUT HOUSEHOLD LEVEL
As mentioned earlier, the connector mimicks the hierarchical structure of the UI. Hence, the definition of functions and parameters are defined on the country level, and their actual implementation are here also accessible via the Tax System. Note that also here, the values of a parameter and the switch of a function can be manipulated through the Python Connector without saving the changes permanently.
# Overview of the functions defined in the bho_se policy
print(mod.countries["SE"].policies[22].functions)
# System specific Implementation of functions
print(mod.countries["SE"].systems["SE_2021"].policies[22].functions)
0: ArithOp | Wealth to be included in the means
1: Allocate | Allocation of wealth to the partners
2: BenCalc | Income of children is not take into account in the ...
3: BenCalc | Families with children - Special component
4: BenCalc | Families with children - Rent component
5: BenCalc | Families with children - Reduction for each partne ...
6: BenCalc | Families with children - Reduction for each partne ...
7: BenCalc | Families with children - Final allowance after red ...
8: ArithOp | Families with children - 25% increase in 2nd half ...
9: BenCalc | Families with children - Lone parents - Reduction
10: ArithOp | Families with children - Lone parents - 25% increa ...
11: Elig | Young families without children
12: BenCalc | Young families without children - Rent component
13: BenCalc | Young families without children - Single - Reducti ...
14: BenCalc | Young families without children - Reduction for ea ...
15: BenCalc | Young families without children - Reduction for ea ...
16: BenCalc | Young families without children - With partner Red ...
17: BenCalc | Housing allowance
0: ArithOp | on | Wealth to be included in the means
1: Allocate | on | Allocation of wealth to the partners
2: BenCalc | on | Income of children is not take into account in the ...
3: BenCalc | on | Families with children - Special component
4: BenCalc | on | Families with children - Rent component
5: BenCalc | on | Families with children - Reduction for each partne ...
6: BenCalc | on | Families with children - Reduction for each partne ...
7: BenCalc | on | Families with children - Final allowance after red ...
8: ArithOp | on | Families with children - 25% increase in 2nd half ...
9: BenCalc | on | Families with children - Lone parents - Reduction
10: ArithOp | on | Families with children - Lone parents - 25% increa ...
11: Elig | on | Young families without children
12: BenCalc | on | Young families without children - Rent component
13: BenCalc | on | Young families without children - Single - Reducti ...
14: BenCalc | on | Young families without children - Reduction for ea ...
15: BenCalc | on | Young families without children - Reduction for ea ...
16: BenCalc | on | Young families without children - With partner Red ...
17: BenCalc | on | Housing allowance
# Overview of the parameters defined in the bho_se policy
print(mod.countries["SE"].policies[22].functions[0].parameters)
# Implementation of parameters
print(mod.countries["SE"].systems["SE_2021"].policies[22].functions[0].parameters)
0: formula | only 15% of wealth exceeding the amount
1: #_amount | "This is the wealth threshold, expressed as ""mont ...
2: output_var | Wealth to be included in the means
3: TAX_UNIT |
0: formula | 0.15*max(afc-amount#1,0) | only 15% of wealth exceeding the amount
1: #_amount | 100000#y | "This is the wealth threshold, expressed as ""mont ...
2: output_var | afc00_s | Wealth to be included in the means
3: TAX_UNIT | tu_bho_se |
Other Important EUROMOD Objects¶
Central to the EUROMOD project, next to the coding of the policies is the microdata. How datasets should be treated by the model is configured in the model already. The attributes of the datasets are just like the spine-elements accessible and modifiable.
mod.countries["SE"].datasets
0: SE_2007_a4
1: SE_2008_a3
2: training_data
3: SE_2010_a1
4: SE_2012_a2
5: SE_2015_a1
6: SE_2009_hhot
7: SE_2010_hhot
8: SE_2011_hhot
9: SE_2012_hhot
10: SE_2013_hhot
11: SE_2014_hhot
12: SE_2015_hhot
13: SE_2016_hhot
14: SE_2017_hhot
15: SE_2016_a1
16: SE_2018_hhot
17: SE_2019_hhot
18: SE_2018_a2
19: SE_2017_a3
20: SE_2020_hhot
21: SE_2010_a1_2010_03_e1
22: SE_2019_a1
23: SE_2020_b1
24: SE_2021_hhot
25: SE_2022_hhot
26: SE_2015_a1_2015_03_e2
27: SE_2021_b1
28: SE_2023_hhot
29: SE_2022_b1
30: SE_2019_a1_2015_03_e2
31: SE_2020_b1_2015_03_e2
32: SE_2021_b1_2015_03_e2
33: SE_2022_b1_2015_03_e2
34: SE_training_data
35: SE_2024_hhot
In the previous section we used SE_2022_b1. Let us have a look at it.
mod.countries["SE"].datasets["SE_2022_b1"]
------------------------------
Dataset
------------------------------
ID: 'f22d52a2-acfe-41c6-852a-e1eaa1540566'
coicopVersion: ''
comment: ''
currency: 'national'
decimalSign: '.'
name: 'SE_2022_b1'
private: 'no'
readXVariables: 'no'
system_elements: 0 elements
useCommonDefault: 'no'
yearCollection: '2022'
yearInc: '2021'
Similar to policies, functions and parameters, can the attributes of the policies be modified here. An other important concept in euromod are extensions and are defined globally on the Model level or locally on the Country level.
mod.countries["SE"].extensions[7]
------------------------------
Extension
------------------------------
ID: '557c232a-9ce6-4808-b52f-ca5e02fe8cf4'
look: '|BUTTON_COLOR=-16744384|'
name: 'Minimum Wage Adjustments'
shortName: 'MWA'
The extensions object is of the type Container, which means that you can index it by the number preceding their name. If we want to access the information stored in the Minimum Wage Adjustments extension for example, one can simply use the following command.
Displaying information about a dataset relative to a system, e.g. dataset ‘sl_demo_v4’ for the system ‘SL_1996’, by indexing the attribute datasets:
mod.countries['SL'].systems['SL_1996'].datasets[0]
------------------------------
DatasetInSystem
------------------------------
ID: 'F7E5CACE-CECC-4BB6-9841-A936D0975481CBA7E428-F8E4-4CEB-8A5E-9ACE73987DD7'
bestMatch: 'no'
coicopVersion: ''
comment: ''
currency: 'euro'
dataID: 'CBA7E428-F8E4-4CEB-8A5E-9ACE73987DD7'
decimalSign: '.'
name: 'sl_demo_v4'
private: 'no'
readXVariables: 'no'
sysID: 'F7E5CACE-CECC-4BB6-9841-A936D0975481'
useCommonDefault: 'no'