Note
Go to the end to download the full example code.
Direct point elasticities
- We use a previously estimated nested logit model and calculate
disaggregate and aggregate direct point elasticities.
Details about this example are available in Section 3 of Bierlaire (2018) Calculating indicators with PandasBiogeme
- author:
Michel Bierlaire, EPFL
- date:
Wed Apr 12 21:01:41 2023
import sys
from IPython.core.display_functions import display
import biogeme.biogeme as bio
from biogeme import models
import biogeme.results as res
from biogeme.exceptions import BiogemeError
from biogeme.expressions import Derive
from biogeme.data.optima import read_data, normalized_weight
from scenarios import (
scenario,
TimePT,
TimeCar,
MarginalCostPT,
CostCarCHF,
distance_km,
)
Obtain the specification for the default scenario The definition of the scenarios is available in Specification of a nested logit model.
V, nests, _, _ = scenario()
Obtain the expression for the choice probability of each alternative.
prob_PT = models.nested(V, None, nests, 0)
prob_CAR = models.nested(V, None, nests, 1)
prob_SM = models.nested(V, None, nests, 2)
Calculation of the direct elasticities. We use the ‘Derive’ operator to calculate the derivatives.
direct_elas_pt_time = Derive(prob_PT, 'TimePT') * TimePT / prob_PT
direct_elas_pt_cost = Derive(prob_PT, 'MarginalCostPT') * MarginalCostPT / prob_PT
direct_elas_car_time = Derive(prob_CAR, 'TimeCar') * TimeCar / prob_CAR
direct_elas_car_cost = Derive(prob_CAR, 'CostCarCHF') * CostCarCHF / prob_CAR
direct_elas_sm_dist = Derive(prob_SM, 'distance_km') * distance_km / prob_SM
Formulas to simulate.
simulate = {
'weight': normalized_weight,
'Prob. car': prob_CAR,
'Prob. public transportation': prob_PT,
'Prob. slow modes': prob_SM,
'direct_elas_pt_time': direct_elas_pt_time,
'direct_elas_pt_cost': direct_elas_pt_cost,
'direct_elas_car_time': direct_elas_car_time,
'direct_elas_car_cost': direct_elas_car_cost,
'direct_elas_sm_dist': direct_elas_sm_dist,
}
Read the data
database = read_data()
Create the Biogeme object.
the_biogeme = bio.BIOGEME(database, simulate)
Read the estimation results from the file
try:
results = res.bioResults(pickle_file='saved_results/b02estimation.pickle')
except BiogemeError:
sys.exit(
'Run first the script b02estimation.py in order to generate '
'the file b02estimation.pickle.'
)
simulated_values is a Pandas dataframe with the same number of rows as the database, and as many columns as formulas to simulate.
simulated_values = the_biogeme.simulate(results.get_beta_values())
display(simulated_values)
weight Prob. car ... direct_elas_car_cost direct_elas_sm_dist
0 0.886023 0.508061 ... -0.179272 -6.416591
2 0.861136 0.574899 ... -0.021838 -0.705481
3 0.861136 0.888093 ... -0.030361 -6.195871
4 0.957386 0.790872 ... -0.027865 -1.431063
5 0.861136 0.733898 ... -0.057884 -4.774826
... ... ... ... ... ...
2259 2.036009 0.710676 ... -0.130517 -10.886598
2261 0.861136 0.849664 ... -0.055027 -8.233209
2262 0.861136 0.688689 ... -0.033734 -1.752372
2263 0.957386 0.747552 ... -0.051470 -3.335287
2264 0.957386 0.767021 ... -0.059843 -3.914194
[1906 rows x 9 columns]
We calculate the aggregate elasticities.
First, the weighted probabilities.
simulated_values['Weighted prob. car'] = (
simulated_values['weight'] * simulated_values['Prob. car']
)
simulated_values['Weighted prob. PT'] = (
simulated_values['weight'] * simulated_values['Prob. public transportation']
)
simulated_values['Weighted prob. SM'] = (
simulated_values['weight'] * simulated_values['Prob. slow modes']
)
Then the denominators of the aggregate elasticity expressions.
denominator_car = simulated_values['Weighted prob. car'].sum()
denominator_pt = simulated_values['Weighted prob. PT'].sum()
denominator_sm = simulated_values['Weighted prob. SM'].sum()
And finally the aggregate elasticities themselves.
Elasticity of car with respect to time.
direct_elas_term_car_time = (
simulated_values['Weighted prob. car']
* simulated_values['direct_elas_car_time']
/ denominator_car
).sum()
print(
f'Aggregate direct point elasticity of car wrt time: '
f'{direct_elas_term_car_time:.3g}'
)
Aggregate direct point elasticity of car wrt time: -0.0353
Elasticity of car with respect to cost.
direct_elas_term_car_cost = (
simulated_values['Weighted prob. car']
* simulated_values['direct_elas_car_cost']
/ denominator_car
).sum()
print(
f'Aggregate direct point elasticity of car wrt cost: '
f'{direct_elas_term_car_cost:.3g}'
)
Aggregate direct point elasticity of car wrt cost: -0.0993
Elasticity of public transportation with respect to time.
direct_elas_term_pt_time = (
simulated_values['Weighted prob. PT']
* simulated_values['direct_elas_pt_time']
/ denominator_pt
).sum()
print(
f'Aggregate direct point elasticity of PT wrt time: '
f'{direct_elas_term_pt_time:.3g}'
)
Aggregate direct point elasticity of PT wrt time: -0.231
Elasticity of public transportation with respect to cost.
direct_elas_term_pt_cost = (
simulated_values['Weighted prob. PT']
* simulated_values['direct_elas_pt_cost']
/ denominator_pt
).sum()
print(
f'Aggregate direct point elasticity of PT wrt cost: '
f'{direct_elas_term_pt_cost:.3g}'
)
Aggregate direct point elasticity of PT wrt cost: -0.366
Elasticity of slow modes with respect to distance.
direct_elas_term_sm_dist = (
simulated_values['Weighted prob. SM']
* simulated_values['direct_elas_sm_dist']
/ denominator_sm
).sum()
print(
f'Aggregate direct point elasticity of SM wrt distance: '
f'{direct_elas_term_sm_dist:.3g}'
)
Aggregate direct point elasticity of SM wrt distance: -1.12
Total running time of the script: (0 minutes 3.228 seconds)