#!/usr/bin/env python # coding: utf-8 #

Table of Contents

#
# # # Importance of giving a convenient period # This notebook aim to show easily how periods work in OpenFisca. # We need to initialize a **simulation**. # In[1]: from openfisca_france import FranceTaxBenefitSystem tax_benefit_system = FranceTaxBenefitSystem() scenario = tax_benefit_system.new_scenario() scenario.init_single_entity( period = 2015, parent1 = dict( age = 30, salaire_de_base = 50000, ), enfants = [ dict(age = 12), dict(age = 18), ], ) simulation = scenario.new_simulation() # A simulation's variable is calculated for a specific period. # This specific time interval have to be given when calling a variable to avoid computation problem. # # ### Variables with monthly formulas # Some variables are computed over the month. # For exemple the variable `allocation familiales`. # If called on an annual basis, an error is displayed : # In[2]: simulation.calculate('af', '2015') # This assertion error : # "`Requested period 2015 differs from 2015-01 returned by variable af`" # means exactly the fact that `af` are computed for a month, therefore the variable returned value for `2015-01`. # But when called on its period (monthly), the result of the variable's formula will be returned # In[3]: simulation.calculate('af', '2015-01') #calculate variable af for January 2015 # ### Variable with annual formulas # Other formulas only works on a annual basis, thus a monthly call will not work, e.g irpp (impôt sur le revenu) : # In[4]: simulation.calculate('irpp', '2015-01') # It must be called on an annual basis : # In[5]: simulation.calculate('irpp', '2015') #calculate variable irpp for 2015 # ### Default period # When a variable is called without period, the simulation's default period is used. # In[6]: simulation.period # Here default simulation period is a year. Thus the variable `irpp` can be computed but not the variable `af`. # In[7]: print(simulation.calculate('irpp')) # In this case simulation.calculate('irpp') is equivalent to simulation.calculate('irpp', '2015') # In[8]: print(simulation.calculate('irpp') == simulation.calculate('irpp', '2015')) # **WARNING** : this demonstration shows the necessity of being aware over which kind of period each measure you want to compute is based on. # # ### How to know the definition period of a variable # # If you've forgotten over which kind of period (year or month) your variable is defined in the legislation, you may check in the [legislation explorer](https://legislation.openfisca.fr/variables). # # The information is located in the code source. # # Example for the  [irpp](https://legislation.openfisca.fr/variables/irpp), a tax with annual definition, you will find the period at the end of the website page: # # ![](irpp_period.png) # # Solutions # Specific period calls insure that no errors are made by the user. # If a annual based variable is asked to be computed monthly, the software returns an error. # # But there is solutions to get the result of a given variable on another kind of period, a annual based variable over a month for example. # ### Calculate_add : small to larger period # The calculate_add method has the same behavior as calculate, except that it sum all variables given their instant of calculus over a period lenght. # In[9]: print simulation.calculate_add("af", "2015") # This result is equivalent to do sum all monthly calculate over the period. # In[10]: annual_af = 0 #create annual_af equals to 0 for month in range(1,13): # [1,2,...,11,12] annual_af += simulation.calculate("af", '2015-{}'.format(month)) #add recursively af for all month in 2014 # In[11]: print annual_af # We thus see that annual_af is equal to simulation.calculate_add('af', "2014"). # # We can test that : # In[12]: print simulation.calculate_add('af','2015') == annual_af # ### Calculate_divide : large to smaller period # In[13]: simulation.calculate_divide("irpp", "2015-01") # In[14]: simulation.calculate("irpp", "2015")/12 # Be warned, when a variable is calculated on a monthly basis with calculate_divide (or add), the result is stored in cache. # # Now you can do : # In[15]: simulation.calculate('irpp', '2015-01') # ### Calculate_add_divide # Some variables are not constant over the year but you might want it as an average value for each month. # # For exemple variable `'ars'` (allocation de rentrée scolaire), is computed only in september. To smooth it over the year, we must use calculate_add_divide. It will simply sum it over a given period, and then divide it over sub-periods of that period. # In[37]: simulation.calculate('ars', '2014')/12 # In[17]: simulation.calculate_add_divide('ars', "2014-08") # Que fait add_divide ? # In[32]: get_ipython().run_line_magic('pinfo2', 'simulation.compute_add_divide') # # The Concept of Period # We can also use more exotic period by using the class periods. # # Actually when we do : `simulation.calculate('irpp','2015')`, the '2015' string is converted into an object period. # # A more explicit way to do this, is : `simulation.calculate('irpp', periods.period('2015'))` # In[20]: from openfisca_core import periods # OpenFisca_core is the architecture of OpenFisca periods.period('2015') # In[21]: print(simulation.calculate('irpp', periods.period('2015'))) print(simulation.calculate('irpp', periods.period('2015'))== simulation.calculate('irpp', 2015)) # ### Definition # We can look at periods docstring to understand how it works : # In[22]: print periods.period.__doc__[: 280] #periods.period? would also display the help, suppress the brackets to get full doc # A *period* is constituted of three parameters: # - A unit : day, month and year # - A start instant : the date at which it starts # - And a size : the number of unit # # periods.period('day','2014-03-01', 32) would be a period going from the first of March to the first of april # ### Computing over several months # If we want to calculate the 'allocation familiales' from the April to July. # In[23]: af_march_to_july = simulation.calculate_add('af' ,periods.period('month', '2015-04', 4)) print af_march_to_july # A simplificated version of period declaration exists with the symbol: `":"`. # # `year-month:n` means n months beginning at the month, year. # # Example with `af_march_to_july`: # In[24]: af_march_to_july = simulation.calculate_add('af' ,'2015-04:4') print af_march_to_july # ### Computing over several years with identique scenario # # Computing over several years needs to rethink how we've declared the scenario: # the starting scenario has, as `period`, one year, `2015`, so it won't be able to compute anything outside this time interval. # # The idea is to change the period over which the scenario applies, using the syntax shown previously. # # **WARNING : handling the stretching of values ** # Doing that defines the other variables for the entire time interval including their values. # In[25]: #we have to give a new scenario scenario_over_years = tax_benefit_system.new_scenario() scenario_over_years.init_single_entity( period = '2014:3', # it means three years starting in 2014 parent1 = dict( date_naissance = 1975, salaire_de_base = 50000 * 3 , # if we want 50000 for each of the three years ), enfants = [ dict(date_naissance = 2001), dict(date_naissance = 1999), ], ) simulation_over_years = scenario_over_years.new_simulation() # **WARNING : handling the age** # We've changed the variable `age` to `date_naissance` in order that the individuals get older. If we've kept the `age` they would have the same age for the entire period. # # Now we can compute the `irpp` with the function previously used : `calculate_add` # In[26]: simulation_over_years.calculate_add('irpp', '2014:2') # for 2014 and 2015 # It takes in consideration the legislation change between the two years. # Therefore it equals the sum of `irpp` for each year but not the double of `irpp` for one year. # In[27]: print(simulation_over_years.calculate('irpp', '2015') + simulation_over_years.calculate('irpp', '2014')) print(simulation_over_years.calculate_add('irpp', '2014')*2) # These formulas are still working for variables defined on a monthly basis. # In[28]: simulation_over_years.calculate_add('af', '2015:2') # ### Computing over several years changing scenario # # You might want to make evolve some given values over the years. # # The tool for it will be to use a Python dictionnary. # # For example, if you want to give a wage evolution : # In[29]: scenario_over_years = tax_benefit_system.new_scenario() scenario_over_years.init_single_entity( period = '2014:3', parent1 = dict( date_naissance = 1975, salaire_de_base = {'2014':50000, '2015': 50500, '2016':51000}, ), enfants = [ dict(date_naissance = 2001), dict(date_naissance = 1999), ], ) simulation_over_years = scenario_over_years.new_simulation() # In[30]: simulation_over_years.calculate_add('irpp', '2014:3') # for 2014, 2015 and 2016 # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # *Command line to get the Notebook's Table of Contents:* # In[31]: get_ipython().run_cell_magic('javascript', '', "$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')\n")