{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

Table of Contents

\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Importance of giving a convenient period" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook aim to show easily how periods work in OpenFisca. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need to initialize a **simulation**." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from openfisca_france import FranceTaxBenefitSystem\n", "tax_benefit_system = FranceTaxBenefitSystem()\n", "scenario = tax_benefit_system.new_scenario()\n", "scenario.init_single_entity(\n", " period = 2015,\n", " parent1 = dict(\n", " age = 30,\n", " salaire_de_base = 50000,\n", " ),\n", " enfants = [\n", " dict(age = 12),\n", " dict(age = 18),\n", " ],\n", " )\n", "simulation = scenario.new_simulation()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simulation's variable is calculated for a specific period. \n", "This specific time interval have to be given when calling a variable to avoid computation problem.\n", "\n", "### Variables with monthly formulas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some variables are computed over the month. \n", "For exemple the variable `allocation familiales`. \n", "If called on an annual basis, an error is displayed : " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unable to compute variable af for period 2015 : af must be computed for a whole month. You can use the ADD option to sum af over the requested period, or change the requested period to \"period.first_month\".\n" ] } ], "source": [ "try:\n", " simulation.calculate('af', '2015')\n", "except Exception as e:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This assertion error : \n", " \"`Requested period 2015 differs from 2015-01 returned by variable af`\" \n", "means exactly the fact that `af` are computed for a month, therefore the variable returned value for `2015-01`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But when called on its period (monthly), the result of the variable's formula will be returned" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([129.99], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate('af', '2015-01') #calculate variable af for January 2015" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Variable with annual formulas" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other formulas only works on a annual basis, thus a monthly call will not work, e.g irpp (impôt sur le revenu) :" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Unable to compute variable irpp for period 2015-01 : irpp must be computed for a whole year. You can use the DIVIDE option to get an estimate of irpp by dividing the yearly value by 12, or change the requested period to \"period.this_year\".\n" ] } ], "source": [ "try:\n", " simulation.calculate('irpp', period = '2015-01')\n", "except Exception as e:\n", " print(e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It must be called on an annual basis :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-2400.528], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate('irpp', period = '2015') #calculate variable irpp for 2015" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**WARNING** : this demonstration shows the necessity of being aware over which kind of period each measure you want to compute is based on.\n", "\n", "### How to know the definition period of a variable\n", "\n", "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://fr.openfisca.org/legislation).\n", "\n", "The information is located in the code source.\n", "\n", "Example for the  [irpp](https://fr.openfisca.org/legislation/irpp), a tax with annual definition, you will find the period at the end of the website page:\n", "\n", "![](irpp_period.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Solutions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Specific period calls insure that no errors are made by the user. \n", "If a annual based variable is asked to be computed monthly, the software returns an error.\n", "\n", "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." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate_add : small to larger period" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1559.88], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate_add(\"af\", \"2015\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This result is equivalent to do sum all monthly calculate over the period." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1559.88], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "annual_af = 0 #create annual_af equals to 0\n", "for month in range(1,13): # [1,2,...,11,12]\n", " annual_af += simulation.calculate(\"af\", '2015-{}'.format(month)) #add recursively af for all month in 2014\n", "annual_af" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We thus see that annual_af is equal to simulation.calculate_add('af', \"2014\").\n", "\n", "We can test that :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ True])" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate_add('af','2015') == annual_af" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate_divide : large to smaller period" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-200.044], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate_divide(\"irpp\", \"2015-01\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-200.044], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation.calculate(\"irpp\", \"2015\") / 12" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The Concept of Period" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also use more exotic period by using the class periods. \n", "\n", "Actually when we do : `simulation.calculate('irpp','2015')`, the '2015' string is converted into an object period. \n", "\n", "A more explicit way to do this, is : `simulation.calculate('irpp', periods.period('2015'))`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Period((u'year', Instant((2015, 1, 1)), 1))" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from openfisca_core import periods # OpenFisca_core is the architecture of OpenFisca\n", "periods.period('2015')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-2400.528]\n", "[ True]\n" ] } ], "source": [ "print(simulation.calculate('irpp', periods.period('2015')))\n", "print(simulation.calculate('irpp', periods.period('2015')) == simulation.calculate('irpp', 2015))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Definition\n", "We can look at periods docstring to understand how it works :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Return a new period, aka a triple (unit, start_instant, size).\n", "\n", " >>> period(u'2014')\n", " Period((YEAR, Instant((2014, 1, 1)), 1))\n", " >>> period(u'year:2014')\n", " Period((YEAR, Instant((2014, 1, 1)), 1))\n", "\n", " >>> period(u'2014-2')\n", " Period((MONTH, Instant((2014, 2, 1)), 1))\n", " >>> period(u'2014-02')\n", " Period((MONTH, Instant((2014, 2, 1)), 1))\n", " >>> period(u'month:2014-2')\n", " Period((MONTH, Instant((2014, 2, 1)), 1))\n", "\n", " >>> period(u'year:2014-2')\n", " Period((YEAR, Instant((2014, 2, 1)), 1))\n", " \n" ] } ], "source": [ "print(periods.period.__doc__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A `Period` object is initialized with three parameters:\n", "- A unit : day, month and year\n", "- A start instant : the date at which it starts\n", "- And a size : the number of unit \n", "\n", "`periods.Period('day', periods.Instant((2014, 3, 01)), 32)` would be a period going from the first of March to the first of april" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('day', Instant((2014, 3, 1)), 32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "period = periods.Period(('day', periods.Instant((2014, 3, 1)), 32)) \n", "period.unit, period.start, period.size" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Computing over several months" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we want to calculate the 'allocation familiales' from the April to July." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[519.18]\n" ] } ], "source": [ "af_april_to_july = simulation.calculate_add(\n", " 'af', \n", " period = periods.Period(('month', periods.Instant((2014, 3, 1)), 4))\n", " )\n", "print(af_april_to_july)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simplificated version of period declaration exists with the symbol: `\":\"`.\n", "\n", "`month:year-month:n` means n months beginning at the month, year.\n", "\n", "Example with `af_april_to_july`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[519.96]\n" ] } ], "source": [ "af_april_to_july = simulation.calculate_add('af', period = periods.period(\"month:2014-04:4\"))\n", "print(af_april_to_july)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A simplified instant declaration of instant also exists " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Instant((2014, 1, 1))" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "periods.instant(\"2014-01\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Computing over several years with identique scenario\n", "\n", "Computing over several years needs to rethink how we've declared the scenario: \n", "the starting scenario has, as `period`, one year, `2015`, so it won't be able to compute anything outside this time interval.\n", "\n", "The idea is to change the period over which the scenario applies, using the syntax shown previously. \n", "\n", "**WARNING : handling the stretching of values ** \n", "Doing that defines the other variables for the entire time interval including their values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# We have to initialise a new scenario\n", "scenario_over_years = tax_benefit_system.new_scenario()\n", "scenario_over_years.init_single_entity(\n", " period = 'year:2014:3', # three years starting in 2014\n", " parent1 = dict(\n", " date_naissance = 1975,\n", " salaire_de_base = 50000 * 3, \n", " # Multiplication by 3 is need so salaire de base is 50000 € for each of the three years\n", " ),\n", " enfants = [\n", " dict(date_naissance = 2001),\n", " dict(date_naissance = 1999),\n", " ],\n", " )\n", "simulation_over_years = scenario_over_years.new_simulation()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**WARNING : handling the age** \n", "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.\n", "\n", "Now we can compute the `irpp` with the function previously used : `calculate_add`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-4813.6865], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation_over_years.calculate_add('irpp', period = 'year:2014-01:2') # for 2014 and 2015" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It takes in consideration the legislation change between the two years. \n", "Therefore it equals the sum of `irpp` for each year but not the double of `irpp` for one year." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-4813.6865]\n", "[-4826.3174]\n" ] } ], "source": [ "print(simulation_over_years.calculate('irpp', '2015') + simulation_over_years.calculate('irpp', '2014'))\n", "print(simulation_over_years.calculate_add('irpp', '2014') * 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These formulas are still working for variables defined on a monthly basis." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([324.97363], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation_over_years.calculate_add('af', 'month:2015-01:2')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Computing over several years changing scenario\n", "\n", "You might want to make evolve some given values over the years.\n", "\n", "The tool for it will be to use a Python dictionnary.\n", "\n", "For example, if you want to give a wage evolution :" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scenario_over_years = tax_benefit_system.new_scenario()\n", "scenario_over_years.init_single_entity(\n", " period = 'year:2014:3',\n", " parent1 = dict(\n", " date_naissance = 1975,\n", " salaire_de_base = {\n", " '2014': 50000, \n", " '2015': 50500, \n", " '2016': 51000\n", " },\n", " ),\n", " enfants = [\n", " dict(date_naissance = 2001),\n", " dict(date_naissance = 1999),\n", " ],\n", " )\n", "simulation_over_years = scenario_over_years.new_simulation()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-7362.9565], dtype=float32)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "simulation_over_years.calculate_add('irpp', 'year:2014:3') # for 2014, 2015 and 2016" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*Command line to get the Notebook's Table of Contents:*" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%javascript\n", "$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 1 }