Calculation of market shares

We use an estimated model to calculate market shares.

Michel Bierlaire, EPFL Sat Jun 28 2025, 18:06:27

import sys

from biogeme.biogeme import BIOGEME
from biogeme.data.optima import normalized_weight, read_data
from biogeme.models import nested
from biogeme.results_processing import EstimationResults

from scenarios import scenario

Obtain the specification for the default scenario

v, nests, _, _ = scenario()

Obtain the expression for the choice probability of each alternative.

prob_pt = nested(v, None, nests, 0)
prob_car = nested(v, None, nests, 1)
prob_sm = nested(v, None, nests, 2)

Read the estimation results from the file

try:
    results = EstimationResults.from_yaml_file(
        filename='saved_results/b02estimation.yaml'
    )
except FileNotFoundError:
    sys.exit(
        'Run first the script b02simulation.py '
        'in order to generate the '
        'file b02estimation.yaml.'
    )

Read the database

database = read_data()

We now simulate the choice probabilities and the weight

simulate = {
    'weight': normalized_weight,
    'Prob. PT': prob_pt,
    'Prob. car': prob_car,
    'Prob. SM': prob_sm,
}

the_biogeme = BIOGEME(database, simulate)
simulated_values = the_biogeme.simulate(results.get_beta_values())

We also calculate confidence intervals for the calculated quantities,

b = results.get_betas_for_sensitivity_analysis()
left, right = the_biogeme.confidence_intervals(b, 0.9)
  0%|          | 0/100 [00:00<?, ?it/s]
  1%|          | 1/100 [00:00<00:55,  1.79it/s]
  2%|▏         | 2/100 [00:01<00:55,  1.77it/s]
  3%|▎         | 3/100 [00:01<00:55,  1.76it/s]
  4%|▍         | 4/100 [00:02<00:56,  1.70it/s]
  5%|▌         | 5/100 [00:02<00:54,  1.73it/s]
  6%|▌         | 6/100 [00:03<00:53,  1.75it/s]
  7%|▋         | 7/100 [00:03<00:52,  1.77it/s]
  8%|▊         | 8/100 [00:04<00:51,  1.78it/s]
  9%|▉         | 9/100 [00:05<00:51,  1.78it/s]
 10%|█         | 10/100 [00:05<00:50,  1.79it/s]
 11%|█         | 11/100 [00:06<00:49,  1.80it/s]
 12%|█▏        | 12/100 [00:06<00:48,  1.80it/s]
 13%|█▎        | 13/100 [00:07<00:48,  1.81it/s]
 14%|█▍        | 14/100 [00:07<00:47,  1.81it/s]
 15%|█▌        | 15/100 [00:08<00:46,  1.82it/s]
 16%|█▌        | 16/100 [00:08<00:46,  1.82it/s]
 17%|█▋        | 17/100 [00:09<00:45,  1.82it/s]
 18%|█▊        | 18/100 [00:10<00:45,  1.82it/s]
 19%|█▉        | 19/100 [00:10<00:44,  1.82it/s]
 20%|██        | 20/100 [00:11<00:44,  1.81it/s]
 21%|██        | 21/100 [00:11<00:43,  1.81it/s]
 22%|██▏       | 22/100 [00:12<00:42,  1.82it/s]
 23%|██▎       | 23/100 [00:12<00:42,  1.82it/s]
 24%|██▍       | 24/100 [00:13<00:41,  1.81it/s]
 25%|██▌       | 25/100 [00:13<00:41,  1.81it/s]
 26%|██▌       | 26/100 [00:14<00:40,  1.81it/s]
 27%|██▋       | 27/100 [00:15<00:40,  1.82it/s]
 28%|██▊       | 28/100 [00:15<00:39,  1.81it/s]
 29%|██▉       | 29/100 [00:16<00:39,  1.82it/s]
 30%|███       | 30/100 [00:16<00:38,  1.81it/s]
 31%|███       | 31/100 [00:17<00:38,  1.81it/s]
 32%|███▏      | 32/100 [00:17<00:37,  1.81it/s]
 33%|███▎      | 33/100 [00:18<00:36,  1.81it/s]
 34%|███▍      | 34/100 [00:18<00:36,  1.82it/s]
 35%|███▌      | 35/100 [00:19<00:35,  1.82it/s]
 36%|███▌      | 36/100 [00:19<00:35,  1.82it/s]
 37%|███▋      | 37/100 [00:20<00:34,  1.82it/s]
 38%|███▊      | 38/100 [00:21<00:34,  1.82it/s]
 39%|███▉      | 39/100 [00:21<00:33,  1.82it/s]
 40%|████      | 40/100 [00:22<00:32,  1.83it/s]
 41%|████      | 41/100 [00:22<00:32,  1.83it/s]
 42%|████▏     | 42/100 [00:23<00:31,  1.82it/s]
 43%|████▎     | 43/100 [00:23<00:31,  1.80it/s]
 44%|████▍     | 44/100 [00:26<01:07,  1.21s/it]
 45%|████▌     | 45/100 [00:27<00:55,  1.01s/it]
 46%|████▌     | 46/100 [00:27<00:47,  1.15it/s]
 47%|████▋     | 47/100 [00:28<00:41,  1.29it/s]
 48%|████▊     | 48/100 [00:28<00:36,  1.42it/s]
 49%|████▉     | 49/100 [00:29<00:33,  1.52it/s]
 50%|█████     | 50/100 [00:29<00:31,  1.60it/s]
 51%|█████     | 51/100 [00:30<00:29,  1.65it/s]
 52%|█████▏    | 52/100 [00:30<00:28,  1.70it/s]
 53%|█████▎    | 53/100 [00:31<00:27,  1.73it/s]
 54%|█████▍    | 54/100 [00:32<00:26,  1.76it/s]
 55%|█████▌    | 55/100 [00:32<00:25,  1.78it/s]
 56%|█████▌    | 56/100 [00:33<00:24,  1.79it/s]
 57%|█████▋    | 57/100 [00:33<00:23,  1.79it/s]
 58%|█████▊    | 58/100 [00:34<00:23,  1.80it/s]
 59%|█████▉    | 59/100 [00:34<00:22,  1.80it/s]
 60%|██████    | 60/100 [00:35<00:22,  1.78it/s]
 61%|██████    | 61/100 [00:35<00:21,  1.78it/s]
 62%|██████▏   | 62/100 [00:36<00:21,  1.78it/s]
 63%|██████▎   | 63/100 [00:37<00:20,  1.79it/s]
 64%|██████▍   | 64/100 [00:37<00:20,  1.79it/s]
 65%|██████▌   | 65/100 [00:38<00:19,  1.80it/s]
 66%|██████▌   | 66/100 [00:38<00:18,  1.80it/s]
 67%|██████▋   | 67/100 [00:39<00:18,  1.81it/s]
 68%|██████▊   | 68/100 [00:39<00:17,  1.81it/s]
 69%|██████▉   | 69/100 [00:40<00:17,  1.81it/s]
 70%|███████   | 70/100 [00:40<00:16,  1.81it/s]
 71%|███████   | 71/100 [00:41<00:16,  1.81it/s]
 72%|███████▏  | 72/100 [00:42<00:15,  1.81it/s]
 73%|███████▎  | 73/100 [00:42<00:14,  1.81it/s]
 74%|███████▍  | 74/100 [00:43<00:14,  1.81it/s]
 75%|███████▌  | 75/100 [00:43<00:13,  1.81it/s]
 76%|███████▌  | 76/100 [00:44<00:13,  1.81it/s]
 77%|███████▋  | 77/100 [00:44<00:12,  1.81it/s]
 78%|███████▊  | 78/100 [00:45<00:12,  1.81it/s]
 79%|███████▉  | 79/100 [00:45<00:11,  1.81it/s]
 80%|████████  | 80/100 [00:46<00:11,  1.80it/s]
 81%|████████  | 81/100 [00:47<00:10,  1.80it/s]
 82%|████████▏ | 82/100 [00:47<00:09,  1.80it/s]
 83%|████████▎ | 83/100 [00:48<00:09,  1.81it/s]
 84%|████████▍ | 84/100 [00:48<00:08,  1.80it/s]
 85%|████████▌ | 85/100 [00:49<00:08,  1.80it/s]
 86%|████████▌ | 86/100 [00:49<00:07,  1.80it/s]
 87%|████████▋ | 87/100 [00:50<00:07,  1.81it/s]
 88%|████████▊ | 88/100 [00:50<00:06,  1.81it/s]
 89%|████████▉ | 89/100 [00:51<00:06,  1.81it/s]
 90%|█████████ | 90/100 [00:52<00:05,  1.79it/s]
 91%|█████████ | 91/100 [00:54<00:11,  1.24s/it]
 92%|█████████▏| 92/100 [00:55<00:08,  1.03s/it]
 93%|█████████▎| 93/100 [00:55<00:06,  1.13it/s]
 94%|█████████▍| 94/100 [00:56<00:04,  1.27it/s]
 95%|█████████▌| 95/100 [00:57<00:03,  1.40it/s]
 96%|█████████▌| 96/100 [00:57<00:02,  1.50it/s]
 97%|█████████▋| 97/100 [00:58<00:01,  1.58it/s]
 98%|█████████▊| 98/100 [00:58<00:01,  1.64it/s]
 99%|█████████▉| 99/100 [00:59<00:00,  1.69it/s]
100%|██████████| 100/100 [00:59<00:00,  1.72it/s]
100%|██████████| 100/100 [00:59<00:00,  1.67it/s]

Market shares are calculated using the weighted mean of the individual probabilities.

Alternative car

simulated_values['Weighted prob. car'] = (
    simulated_values['weight'] * simulated_values['Prob. car']
)
left['Weighted prob. car'] = left['weight'] * left['Prob. car']
right['Weighted prob. car'] = right['weight'] * right['Prob. car']

market_share_car = simulated_values['Weighted prob. car'].mean()
market_share_car_left = left['Weighted prob. car'].mean()
market_share_car_right = right['Weighted prob. car'].mean()

Alternative public transportation

simulated_values['Weighted prob. PT'] = (
    simulated_values['weight'] * simulated_values['Prob. PT']
)
left['Weighted prob. PT'] = left['weight'] * left['Prob. PT']
right['Weighted prob. PT'] = right['weight'] * right['Prob. PT']

market_share_pt = simulated_values['Weighted prob. PT'].mean()
market_share_pt_left = left['Weighted prob. PT'].mean()
market_share_pt_right = right['Weighted prob. PT'].mean()

Alternative slow modes

simulated_values['Weighted prob. SM'] = (
    simulated_values['weight'] * simulated_values['Prob. SM']
)
left['Weighted prob. SM'] = left['weight'] * left['Prob. SM']
right['Weighted prob. SM'] = right['weight'] * right['Prob. SM']

market_share_sm = simulated_values['Weighted prob. SM'].mean()
market_share_sm_left = left['Weighted prob. SM'].mean()
market_share_sm_right = right['Weighted prob. SM'].mean()

Reporting.

Car.

print(
    f'Market share for car: {100 * market_share_car:.1f}% '
    f'[{100 * market_share_car_left:.1f}%, '
    f'{100 * market_share_car_right:.1f}%]'
)
Market share for car: 65.2% [61.4%, 68.8%]

Public transportation.

print(
    f'Market share for PT:  {100 * market_share_pt:.1f}% '
    f'[{100 * market_share_pt_left:.1f}%, '
    f'{100 * market_share_pt_right:.1f}%]'
)
Market share for PT:  28.2% [24.5%, 32.2%]

Slow modes.

print(
    f'Market share for SM:   {100 * market_share_sm:.1f}% '
    f'[{100 * market_share_sm_left:.1f}%, '
    f'{100 * market_share_sm_right:.1f}%]'
)
Market share for SM:   6.6% [4.3%, 9.2%]

Total running time of the script: (1 minutes 1.181 seconds)

Gallery generated by Sphinx-Gallery