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. This can be imported as follows:
from euromod import Model
Create an object of the Model class by passing the path to the EUROMOD project:
mod=Model(r"C:\EUROMOD_RELEASES_I6.0+")
mod
------------------------------
Model
------------------------------
countries: 28 elements
extensions: 11 elements
model_path: 'C:\\EUROMOD_RELEASES_I6.0+'
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 contain elements of the respective objects. If we take a look at 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
The countries attirbute is a container storing the Country objects nesting the country-specific tax-benefit policies and systems. We see indeed that the euromod model contains 28 countries.
Note
The elements in an attribute of type Container can be accessed by indexing the attribute with the element position.
In a similar fashion we can look what kind of extensions are stored in the model.
Tip
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
------------------------------
datasets: 27 elements
extensions: 12 elements
local_extensions: COVID
name: 'SE'
policies: 26 elements
systems: 18 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 object. We can obtain the systems for Sweden as follows:
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
Tip
The systems container can be indexed by both the number of the element and the system name.
Running a simulation¶
In order to run the tax system we need a dataset that fits the requirement to use.
See also
See Other important euromod objects on what datasets are configured and how.
If you know already which dataset to use you can simply load the data and run the model as follows:
import pandas as pd
data=pd.read_csv(r"C:\EUROMOD_RELEASES_I6.0+\Input\SE_2021_b1.txt",sep="\t")
out_baseline = mod.countries["SE"].systems["SE_2021"].run(data,"SE_2021_b1")
out_baseline
Simulation for system SE_2021 with dataset SE_2021_b1 finished.
------------------------------
Simulation
------------------------------
constantsToOverwrite: {}
errors: []
output_filenames: ['se_2021_std.txt']
outputs: Pandas DataFrame of 240 variables and 21671 observations.
Note that the run function here takes the mandatory argument dataset_id, which in our case is SE_2021_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. The one of interest here is outputs, which contains the outputdataset(s) returned by the microsimulation model:
out_baseline.outputs[0]
| idhh | idperson | idmother | ... | tu_bho_se_IsDependentChild | tu_bho_se_IsLoneParent | tu_bho_se_IsPartner | |
|---|---|---|---|---|---|---|---|
| 0 | 200.0 | 20001.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 |
| 1 | 300.0 | 30001.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 |
| 2 | 300.0 | 30002.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 |
| 3 | 500.0 | 50001.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 |
| 4 | 500.0 | 50002.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 21666 | 1936500.0 | 193650002.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 |
| 21667 | 1936800.0 | 193680001.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 |
| 21668 | 1936800.0 | 193680002.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 |
| 21669 | 1936800.0 | 193680003.0 | 193680002.0 | ... | 1.0 | 0.0 | 0.0 |
| 21670 | 1936800.0 | 193680004.0 | 193680002.0 | ... | 1.0 | 0.0 | 0.0 |
21671 rows × 240 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 to 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: bunct_se | | BEN: unemployment benefit (contributory)
13: bfapl_se | (with switch set for PBE) | BEN: Parental leave benefit
14: bpa_se | (with switch set for PBE) | BEN: Special leave days other parent (10 days)
15: tscee_se | | SIC: Employee Social Insurance contribution
16: tscer_se | | SIC: Employer Social Insurance contribution
17: tscse_se | | SIC: Self-employed Social Insurance contribution
18: tin_se | | TAX: Personal Income tax
19: tinkt_se | | TAX: Tax on Capital Income
20: bch_se | | BEN: Child benefit
21: bho_se | | BEN: Housing allowance
22: bhope_se | | BEN: Housing allowance for pensioners
23: bsamt_se | | BEN: Social Assistance (means-tested)
24: output_std_se | | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
25: output_std_hh_se | | DEF: STANDARD OUTPUT HOUSEHOLD LEVEL
As one can see the policies attribute is a Container object therefor it’s elements, which are of the type Policy here, are accessible by indexing:
mod.countries["SE"].policies[12]
------------------------------
Policy
------------------------------
ID: '01f1c7ff-3b6d-4191-bc71-bb86db5603d6'
comment: 'BEN: unemployment benefit (contributory)'
extensions: 0 elements
functions: 16 elements
name: 'bunct_se'
order: '13'
private: 'no'
spineOrder: '13'
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: bunct_se | off | BEN: unemployment benefit (contributory)
13: bfapl_se | off (with switch set for PBE) | BEN: Parental leave benefit
14: bpa_se | off (with switch set for PBE) | BEN: Special leave days other parent (10 days)
15: tscee_se | on | SIC: Employee Social Insurance contribution
16: tscer_se | on | SIC: Employer Social Insurance contribution
17: tscse_se | on | SIC: Self-employed Social Insurance contribution
18: tin_se | on | TAX: Personal Income tax
19: tinkt_se | on | TAX: Tax on Capital Income
20: bch_se | on | BEN: Child benefit
21: bho_se | on | BEN: Housing allowance
22: bhope_se | on | BEN: Housing allowance for pensioners
23: bsamt_se | on | BEN: Social Assistance (means-tested)
24: output_std_se | on | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
25: 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[12]
------------------------------
PolicyInSystem
------------------------------
ID: 'bde78132-3f44-4d2e-a1ea-4849f88c277601f1c7ff-3b6d-4191-bc71-bb86db5603d6'
comment: 'BEN: unemployment benefit (contributory)'
extensions: 0 elements
functions: 16 elements
name: 'bunct_se'
order: '13'
polID: '01f1c7ff-3b6d-4191-bc71-bb86db5603d6'
private: 'no'
spineOrder: '13'
switch: 'off'
sysID: 'bde78132-3f44-4d2e-a1ea-4849f88c2776'
We see here the attribute switch that is part of the PolicyInSystem class. This attribute, and similarly the other attributes of the object, is modifiable and the changes that you will make will be passed to the EUROMOD software when simulating.
Important
Currently, the python connector does not support the save option. Therefore, changes implemented during a Python session cannot be saved.
To apply permanent changes to the model, we recommend using the User Interface of EUROMOD.
Attention
Note that the python connector is not checking what kind of modifications you make to the model. Changing values of attributes like ID’s are definitely not recommended.
mod.countries["SE"].systems["SE_2021"].policies[13].switch = 'on'
out_with_bunct_se = mod.countries["SE"].systems["SE_2021"].run(data,"SE_2021_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_2021_b1 finished.
0.0
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: bunct_se | off | BEN: unemployment benefit (contributory)
13: bfapl_se | on (with switch set for PBE) | BEN: Parental leave benefit
14: bpa_se | off (with switch set for PBE) | BEN: Special leave days other parent (10 days)
15: tscee_se | on | SIC: Employee Social Insurance contribution
16: tscer_se | on | SIC: Employer Social Insurance contribution
17: tscse_se | on | SIC: Self-employed Social Insurance contribution
18: tin_se | on | TAX: Personal Income tax
19: tinkt_se | on | TAX: Tax on Capital Income
20: bch_se | on | BEN: Child benefit
21: bho_se | on | BEN: Housing allowance
22: bhope_se | on | BEN: Housing allowance for pensioners
23: bsamt_se | on | BEN: Social Assistance (means-tested)
24: output_std_se | on | DEF: STANDARD OUTPUT INDIVIDUAL LEVEL
25: 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:
print("Overview of the functions defined in the bho_se policy:")
print(mod.countries["SE"].policies[22].functions)
print("System specific Implementation of functions:")
print(mod.countries["SE"].systems["SE_2021"].policies[22].functions)
Overview of the functions defined in the bho_se policy:
0: DefVar | Temporary variables for Housing Allowance for pens ...
1: Elig | Living with partner
2: ArithOp | Wealth to be included in the means
3: Elig | Living without partner
4: ArithOp | Wealth to be included in the means
5: Allocate | Allocation of wealth to the partners
6: Elig | Elderly or disabled adult (i.e. head or partner)
7: BenCalc | "Reserved amount (""income disregard"")"
8: BenCalc | Change in definition of Income Means for for Housi ...
9: DefIl | Income Means for Housing Allowance for pensioners
10: BenCalc | Income of children is not take into account in the ...
11: BenCalc | Maximum housing allowance
12: BenCalc |
13: BenCalc | Maximum housing allowance
14: BenCalc | Maximum housing allowance
15: Allocate | Allocation of income to the partners
16: BenCalc | Final housing allowance for pensioners
17: Allocate | Sharing housing cost
18: BenCalc | Housing allowance for pensioners
System specific Implementation of functions:
0: DefVar | on | Temporary variables for Housing Allowance for pens ...
1: Elig | on | Living with partner
2: ArithOp | on | Wealth to be included in the means
3: Elig | on | Living without partner
4: ArithOp | on | Wealth to be included in the means
5: Allocate | on | Allocation of wealth to the partners
6: Elig | on | Elderly or disabled adult (i.e. head or partner)
7: BenCalc | on | "Reserved amount (""income disregard"")"
8: BenCalc | on | Change in definition of Income Means for for Housi ...
9: DefIl | on | Income Means for Housing Allowance for pensioners
10: BenCalc | on | Income of children is not take into account in the ...
11: BenCalc | on | Maximum housing allowance
12: BenCalc | off |
13: BenCalc | off | Maximum housing allowance
14: BenCalc | on | Maximum housing allowance
15: Allocate | on | Allocation of income to the partners
16: BenCalc | on | Final housing allowance for pensioners
17: Allocate | on | Sharing housing cost
18: BenCalc | on | Housing allowance for pensioners
print("Overview of the parameters defined in the bho_se policy:")
print(mod.countries["SE"].policies[22].functions[0].parameters)
print("Implementation of parameters:")
print(mod.countries["SE"].systems["SE_2021"].policies[22].functions[0].parameters)
Overview of the parameters defined in the bho_se policy:
0: i_means_bhope_prel
Implementation of parameters:
0: i_means_bhope_prel | 0
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_2019_a1
22: SE_2020_b1
23: SE_2021_hhot
24: SE_2022_hhot
25: SE_2021_b1
26: SE_2023_hhot
In the previous section we used SE_2021_b1. Let us have a look at it.
mod.countries["SE"].datasets["SE_2021_b1"]
------------------------------
Dataset
------------------------------
ID: 'c7b651ed-b311-4e39-80b4-18ca19957ce7'
coicopVersion: ''
comment: ''
currency: 'national'
decimalSign: '.'
name: 'SE_2021_b1'
private: 'no'
readXVariables: 'no'
useCommonDefault: 'no'
yearCollection: '2021'
yearInc: '2020'
Similarly to the attributes in the Policy, Function and Parameter objects, the attributes of the Dataset can be modified here.
We can further check what datasets are implemented for a given system, for example SE_2021, as follows:
mod.countries["SE"]["SE_2021"].datasets
0: training_data |
1: SE_2019_a1 |
2: SE_2020_b1 |
3: SE_2021_hhot |
4: SE_2021_b1 | best match
Another important concept in euromod are extensions that are defined globally on the Model level:
mod.extensions
0: Benefit Take-up Adjustments
1: Tax Compliance Adjustments
2: Full Year Adjustments
3: Uprating by Average Adjustment
4: Extended Policy Simulation
5: Parental leave benefits
6: Minimum Wage Adjustments
7: HHoT unemployment extension
8: EUROMOD JRC-Interface
9: HHoT - Extended Simulation
10: HHoT - Non Compulsory Payments
Or locally on the Country level:
mod.countries["SE"].extensions
0: COVID benefit
1: Benefit Take-up Adjustments
2: Tax Compliance Adjustments
3: Full Year Adjustments
4: Uprating by Average Adjustment
5: Extended Policy Simulation
6: Parental leave benefits
7: Minimum Wage Adjustments
8: HHoT unemployment extension
9: EUROMOD JRC-Interface
10: HHoT - Extended Simulation
11: HHoT - Non Compulsory Payments
The extensions attribute is of type Container. If we want to access the information stored in the Minimum Wage Adjustments extension for example, we can simply use the following command:
mod.countries["SE"].extensions[7]
------------------------------
Extension
------------------------------
ID: '557c232a-9ce6-4808-b52f-ca5e02fe8cf4'
look: '|BUTTON_COLOR=-16744384|'
name: 'Minimum Wage Adjustments'
shortName: 'MWA'