Examples

Loading and navigating the model

We start with importing the euromod package and creating a Model object from a EUROMOD model.

from euromod import Model
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.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

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
mod.countries["SE"].policies[0:10]
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 

Running a system with default configuration

Say that we are interested in running the tax system for the year 2021 of Sweden. Building further on the previous example we can look at the tax-systems contained in the model for 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

In order to run the tax system we need a dataset that fits the requirement to use. The model however provides us with a list of datasets that are configured already.

mod.countries["SE"].systems["SE_2021"].datasets
0: training_data              |             
1: SE_2010_a1_2010_03_e1      |             
2: SE_2019_a1                 |             
3: SE_2020_b1                 |             
4: SE_2021_hhot               |             
5: SE_2015_a1_2015_03_e2      |             
6: SE_2021_b1                 |             
7: SE_2022_b1                 | best match  
8: SE_2019_a1_2015_03_e2      |             
9: SE_2020_b1_2015_03_e2      |             
10: SE_2021_b1_2015_03_e2     |             
11: SE_2022_b1_2015_03_e2     |             
12: SE_training_data          |             

Here we see that there are multiple datasets configured, but that PL_2020_b2 is seen as the best match dataset for this taxsystem. Provided that you have the microdata stored somewhere, you can then load it as a pandas.DataFrame and run the model in the following way:

import pandas as pd
data=pd.read_csv(r"C:\Users\serruha\DATA\2022 datasets\SE_2022_b1.txt",sep="\t")
out = mod.countries["SE"].systems["SE_2021"].run(data,"SE_2022_b1")
out
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.

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.

outputdata_baseline = out.outputs[0]
outputdata_baseline
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

Running a system while changing a constant

One of the advantages of using the Python Connectors is the ability to run many counterfactual scenario’s for the EUROMOD model. One can for example change the Tax Free income limit in Poland. There are multiple ways to do this via the euromod package in Python, but one very straightforward way is to use the constantsToOverwrite option which is a a dictionary, having the targetted constant as a key and the value to overwrite with as a value.

out=mod['SE']['SE_2021'].run(data,"SE_2022_b1",constantsToOverwrite={("$tinna_rate2",""):'0.4'})
outputdata_changed= out.outputs[0]
sum(outputdata_changed.ils_dispy - outputdata_baseline.ils_dispy)
Simulation for system SE_2021 with dataset SE_2022_b1 finished.
-10865920.25980736

The optional parameter constantsToOverwrite specifies which constants to overwrite in the policy spline. constantsToOverwrite must be a dict, where the keys are tuples of two str objects: the first string is the name of the constant and the second string is its group number (Note: Pass an empty string if the group number is None); the values are str with the new values of the constants. The default is None.

Run with add-ons

Run the simulation for the Swedish system SE_2022 including the Marginal Tax-Rate add-on ‘MTR’.

out =mod['SE']['SE_2022'].run(data,"SE_2022_b1",addons=[("MTR","MTR")])
out
Simulation for system SE_2022 with dataset SE_2022_b1 finished.
------------------------------
Simulation
------------------------------
	 constantsToOverwrite: {}
	 errors: []
	 output_filenames: ['se_2022_base_mtr.txt', 'se_2022_mtr.txt']
	 outputs: Pandas DataFrame of 251 variables and 20448 observations., Pandas DataFrame of 38 variables and 20448 observations.

As one can see there are two datasets returned by the model. Both of them can be accessed. The average marginal tax rate for example can then be straightforwardly computed as

out.outputs['se_2022_mtr.txt'].mtrpc.mean()
19.775249709324303

The optional parameter addons that we passed to the run command is a list of EUROMOD Addons to be integrated in the spine . Each item of the list is a tuple with two str objects. The first str is the name of the Addon and the second str is the name of the system in the Addon to be integrated (typically, it is the name of the Addon _ two-letter country code, e.g. LMA_AT). The default valuye here is [].

Run with extensions

Run the simulation for the Swedish system SE_2022 switching on the Benefit Take-up Adjustment extension ‘BTA’.

out_BTA =mod['SE']['SE_2022'].run(data,"SE_2022_b1",switches=[("BTA",True)])
out
Simulation for system SE_2022 with dataset SE_2022_b1 finished.
------------------------------
Simulation
------------------------------
	 constantsToOverwrite: {}
	 errors: []
	 output_filenames: ['se_2022_base_mtr.txt', 'se_2022_mtr.txt']
	 outputs: Pandas DataFrame of 251 variables and 20448 observations., Pandas DataFrame of 38 variables and 20448 observations.
out_BTA.outputs[0].ils_ben.mean() - outputdata_baseline.ils_ben.mean()
169.6445978333495

The optional parameter switches must define a list of the EUROMOD extensions to be switched on or off in the simulation. Each item in the list is a tuple with two objects. The first object is a str short name of the Extension. The second object is a boolean. The default is [].