From afc0e9878964e15087a55288937485ddd7b024c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Oct 2026 23:38:43 +0000 Subject: [PATCH 1/2] Initial plan From 835e95fce1713230c6db43240c2423a3272a9ace Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Oct 2026 23:41:01 +0000 Subject: [PATCH 2/2] Apply remaining changes Co-authored-by: stefancoe <1302855+stefancoe@users.noreply.github.com> --- .../24_park_and_ride_lot_choice.ipynb | 1458 +++++++++++++++++ 1 file changed, 1458 insertions(+) create mode 100644 activitysim/examples/example_estimation/notebooks/24_park_and_ride_lot_choice.ipynb diff --git a/activitysim/examples/example_estimation/notebooks/24_park_and_ride_lot_choice.ipynb b/activitysim/examples/example_estimation/notebooks/24_park_and_ride_lot_choice.ipynb new file mode 100644 index 0000000000..e2c38deebc --- /dev/null +++ b/activitysim/examples/example_estimation/notebooks/24_park_and_ride_lot_choice.ipynb @@ -0,0 +1,1458 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "aa380b96", + "metadata": {}, + "source": [ + "# Estimating Park-and-Ride Lot Choice\n", + "\n", + "This notebook estimates the single-segment park-and-ride lot choice model with Larch. The model is an interaction model, so it uses chooser-alternative expression values from the ActivitySim estimation data bundle.\n", + "\n", + "Run ActivitySim in estimation mode first. The estimation run must include the park-and-ride fixes that preserve `pnr_zone_id` and configure it as the alternative ID." + ] + }, + { + "cell_type": "markdown", + "id": "0fc282d4", + "metadata": {}, + "source": [ + "## Load libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 255, + "id": "5b0bb89c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'larch': '6.0.46',\n", + " 'sharrow': '2.16.2',\n", + " 'numpy': '2.2.6',\n", + " 'pandas': '2.3.2',\n", + " 'xarray': '2025.6.1',\n", + " 'numba': '0.62.0',\n", + " 'jax': 'not installed'}" + ] + }, + "execution_count": 255, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from pathlib import Path\n", + "from types import SimpleNamespace\n", + "\n", + "import larch as lx\n", + "import pandas as pd\n", + "\n", + "from activitysim.estimation.larch.general import (\n", + " apply_coefficients,\n", + " linear_utility_from_spec,\n", + " update_coefficients,\n", + ")\n", + "\n", + "lx.versions()" + ] + }, + { + "cell_type": "markdown", + "id": "b75db7a9", + "metadata": {}, + "source": [ + "## Locate the estimation data bundle\n", + "\n", + "Change `EDB_DIRECTORY` if your ActivitySim output directory is elsewhere." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "068f1c00", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "WindowsPath('C:/workspace/asim_estimation_pnr/outputs_test2/estimation_data_bundle/park_and_ride_lot_choice')" + ] + }, + "execution_count": 256, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "modelname = \"park_and_ride_lot_choice\"\n", + "EDB_DIRECTORY = Path(f\"output-est-mode/estimation_data_bundle/{modelname}/\")\n", + "#EDB_DIRECTORY = Path(r\"C:\\workspace\\asim_estimation_pnr\\outputs_test2\\estimation_data_bundle\") / modelname\n" + ] + }, + { + "cell_type": "code", + "execution_count": 257, + "id": "00ccf73d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using coefficient file: park_and_ride_lot_choice_park_and_ride_lot_choice_coeffs.csv\n" + ] + }, + { + "data": { + "text/plain": [ + "( value constrain\n", + " coefficient_name \n", + " coef_zero 0.000000 T\n", + " coef_unavailable -999.000000 F\n", + " coef_ivt_auto -0.077806 F\n", + " coef_ivt_transit -0.048312 F\n", + " coef_auto_op_costs 0.000000 F,\n", + " Label Description \\\n", + " 4 util_drive_time round trip drive time from origin to lot \n", + " 5 util_total_wait total wait time \n", + " 6 util_walk_time walk time \n", + " 7 util_ivtt in vehcile transit time \n", + " 8 util_log_lot_capacity log_lot_capacity \n", + " \n", + " Expression coefficient \n", + " 4 @_d_pnr_time_skims_out + _d_pnr_time_skims_inb coef_ivt_auto \n", + " 5 @(ldt_skims['twtwpnr'] + dlt_skims['twtwpnr']) coef_wait_transit \n", + " 6 @(ldt_skims['auxwpnr'] + dlt_skims['auxwpnr']) coef_walk_transit \n", + " 7 @(ldt_skims['ivtwpnr'] + dlt_skims['ivtwpnr']) coef_ivt_transit \n", + " 8 @np.log1p(df.PNR_SPACES) coef_lot_capacity ,\n", + " zone_id pnr_zone_id tour_id util_percent_drive util_detour_dist \\\n", + " 0 66235 66235 14814610 1.642785 1.506485 \n", + " 1 66235 66235 14612890 1.060166 1.274534 \n", + " 2 66235 66235 13362800 0.747871 0.838699 \n", + " 3 66235 66235 12625210 1.569609 1.038468 \n", + " 4 66235 66235 11764210 0.763866 1.177020 \n", + " \n", + " util_drive_time util_drive_tolls util_first_wait util_xfer_wait \\\n", + " 0 74.881622 0.0 15.713741 12.450089 \n", + " 1 50.089542 0.0 21.000000 14.318184 \n", + " 2 39.652969 0.0 17.753656 18.809252 \n", + " 3 75.346634 0.0 21.000000 16.810909 \n", + " 4 56.118599 0.0 21.000000 26.178574 \n", + " \n", + " util_total_wait util_walk_time util_ivtt util_transfer_penalty \\\n", + " 0 28.163830 14.494038 35.463264 2.000000 \n", + " 1 35.318184 96.828720 64.872787 2.545455 \n", + " 2 36.562908 27.354671 54.604248 2.382142 \n", + " 3 37.810909 11.533979 104.680817 2.525692 \n", + " 4 47.178574 12.995800 92.420982 4.000000 \n", + " \n", + " util_log_lot_capacity \n", + " 0 5.968708 \n", + " 1 5.968708 \n", + " 2 5.968708 \n", + " 3 5.968708 \n", + " 4 5.968708 ,\n", + " tour_id model_choice override_choice person_id tour_type \\\n", + " 0 214174 66287 66287.0 5223 school \n", + " 1 694210 66298 66287.0 16931 work \n", + " 2 1009948 66287 66283.0 24632 social \n", + " 3 1604820 66305 66338.0 39141 work \n", + " 4 1899200 66236 66260.0 46321 work \n", + " \n", + " tour_type_count tour_type_num tour_num tour_count tour_category ... \\\n", + " 0 1 1 1 1 mandatory ... \n", + " 1 1 1 1 1 mandatory ... \n", + " 2 1 1 1 1 non_mandatory ... \n", + " 3 1 1 1 1 mandatory ... \n", + " 4 1 1 1 1 mandatory ... \n", + " \n", + " cost_sensitivity sov_auto_op_cost coef_ivt coef_inc_adj_cost \\\n", + " 0 500.000000 32.5 -0.017 -0.262 \n", + " 1 63.095734 32.5 -0.016 -0.625 \n", + " 2 132.287566 32.5 -0.017 -0.262 \n", + " 3 923.006654 32.5 -0.016 -0.625 \n", + " 4 1399.016476 32.5 -0.016 -0.625 \n", + " \n", + " income_exponent c_cost time_factor c_ivt vot_d_pnr vot_bin_d_pnr \n", + " 0 0.5 -0.000524 0.480450 -0.008168 9.352262 1 \n", + " 1 0.6 -0.009906 1.671230 -0.026740 1.619674 1 \n", + " 2 0.5 -0.001981 0.534573 -0.009088 2.753117 1 \n", + " 3 0.6 -0.000677 0.942869 -0.015086 13.367421 2 \n", + " 4 0.6 -0.000447 0.537450 -0.008599 11.549205 2 \n", + " \n", + " [5 rows x 202 columns])" + ] + }, + "execution_count": 257, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def read_edb_file(filename, **kwargs):\n", + " path = EDB_DIRECTORY / filename\n", + " parquet_path = path.with_suffix(\".parquet\")\n", + " if parquet_path.exists():\n", + " return pd.read_parquet(parquet_path, **kwargs)\n", + " if not path.exists():\n", + " raise FileNotFoundError(\n", + " f\"Missing {path.name}. Re-run ActivitySim estimation after setting \"\n", + " f\"the park-and-ride chooser ID, then coalesce the interaction EDB.\"\n", + " )\n", + " return pd.read_csv(path, **kwargs)\n", + "\n", + "coefficient_candidates = [\n", + " f\"{modelname}_coefficients.csv\",\n", + " f\"{modelname}_{modelname}_coeffs.csv\",\n", + " f\"{modelname}_coeffs.csv\",\n", + "]\n", + "coefficient_file = next(\n", + " (filename for filename in coefficient_candidates if (EDB_DIRECTORY / filename).exists()),\n", + " None,\n", + ")\n", + "if coefficient_file is None:\n", + " raise FileNotFoundError(\n", + " f\"Could not find PNR coefficients in {EDB_DIRECTORY}. \"\n", + " f\"Expected one of: {coefficient_candidates}\"\n", + " )\n", + "\n", + "coefficients = read_edb_file(coefficient_file, index_col=\"coefficient_name\")\n", + "spec = read_edb_file(f\"{modelname}_SPEC.csv\", comment=\"#\")\n", + "alternatives = read_edb_file(f\"{modelname}_alternatives_combined.csv\")\n", + "choosers = read_edb_file(f\"{modelname}_choosers_combined.csv\")\n", + "\n", + "if \"pnr_zone_id\" not in alternatives.columns:\n", + " raise KeyError(f\"Expected 'pnr_zone_id' in alternatives: {alternatives.columns.tolist()}\")\n", + "chooser_id_column = choosers.columns[0]\n", + "if chooser_id_column not in alternatives.columns:\n", + " raise ValueError(\n", + " f\"The alternatives EDB is missing chooser ID {chooser_id_column!r}. \"\n", + " \"Re-run estimation after setting estimator.set_chooser_id(...) in the \"\n", + " \"park-and-ride model.\"\n", + " )\n", + "\n", + "spec = spec.loc[spec.Expression.notna()].copy()\n", + "spec = spec.loc[~spec.Expression.str.startswith(\"_\")].copy()\n", + "print(f\"Using coefficient file: {coefficient_file}\")\n", + "coefficients.head(), spec.head(), alternatives.head(), choosers.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 258, + "id": "bb13b53a", + "metadata": {}, + "outputs": [], + "source": [ + "# Optional: exclude survey tours with a ~$17.90 toll on the home-to-lot leg (likely ferry); the toll is not modeled\n", + "# EXCLUDED_TOUR_IDS = [10431751, 9927843]\n", + "# alternatives = alternatives.loc[~alternatives[chooser_id_column].isin(EXCLUDED_TOUR_IDS)].copy()\n", + "# choosers = choosers.loc[~choosers[chooser_id_column].isin(EXCLUDED_TOUR_IDS)].copy()" + ] + }, + { + "cell_type": "markdown", + "id": "3dbc8ad2", + "metadata": {}, + "source": [ + "## Build the Larch interaction model\n", + "\n", + "The first two columns of `alternatives_combined` identify the chooser and alternative. The chooser table contains the observed choice written by ActivitySim. PNR uses `pnr_zone_id` as the alternative ID." + ] + }, + { + "cell_type": "code", + "execution_count": 259, + "id": "aaa06ea2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CA index: ['tour_id', 'pnr_zone_id'], unique=True, rows=5733\n", + "CO index: tour_id, unique=True, rows=39\n" + ] + }, + { + "data": { + "text/html": [ + "
keyvalue
ca
['util_drive_time',\n",
+       " 'util_ivtt',\n",
+       " 'util_log_lot_capacity',\n",
+       " 'util_total_wait',\n",
+       " 'util_walk_time']
choice_co_code'override_choice'
avail_anyTrue
" + ], + "text/plain": [ + "┣ ca: ['util_drive_time',\n", + "┃ 'util_ivtt',\n", + "┃ 'util_log_lot_capacity',\n", + "┃ 'util_total_wait',\n", + "┃ 'util_walk_time']\n", + "┣ choice_co_code: 'override_choice'\n", + "┣ avail_any: True" + ] + }, + "execution_count": 259, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "########Build the interaction model\n", + "alternative_id_column = \"pnr_zone_id\"\n", + "\n", + "if alternative_id_column not in alternatives.columns:\n", + " raise KeyError(f\"Expected {alternative_id_column!r} in alternatives: {alternatives.columns.tolist()}\")\n", + "\n", + "key_columns = [chooser_id_column, alternative_id_column]\n", + "duplicate_count = int(alternatives.duplicated(key_columns).sum())\n", + "if duplicate_count:\n", + " print(f\"Removing {duplicate_count} duplicate chooser-alternative rows from the EDB\")\n", + " alternatives = alternatives.drop_duplicates(key_columns, keep=\"last\").copy()\n", + "\n", + "x_ca = alternatives.set_index(key_columns)\n", + "choosers = choosers.drop_duplicates(chooser_id_column, keep=\"last\").copy()\n", + "x_co = choosers.loc[choosers[chooser_id_column].isin(alternatives[chooser_id_column])].set_index(chooser_id_column)\n", + "\n", + "print(f\"CA index: {x_ca.index.names}, unique={x_ca.index.is_unique}, rows={len(x_ca)}\")\n", + "print(f\"CO index: {x_co.index.name}, unique={x_co.index.is_unique}, rows={len(x_co)}\")\n", + "\n", + "choice_candidates = [\"override_choice\", \"model_choice\", \"choice\", \"pnr_zone_id\"]\n", + "choice_column = next((c for c in choice_candidates if c in x_co.columns), None)\n", + "if choice_column is None:\n", + " raise KeyError(f\"Could not find an observed choice column in {x_co.columns.tolist()}\")\n", + "\n", + "# Keep constant chooser-alternative variables two-dimensional for Larch.\n", + "d_ca = lx.Dataset.construct.from_idca(x_ca, crack=False)\n", + "d_co = lx.Dataset.construct.from_idco(x_co)\n", + "datatree = d_ca.merge(d_co)\n", + "\n", + "model = lx.Model(datatree=datatree, compute_engine=\"numba\")\n", + "alt_codes = datatree.dc.altids()\n", + "root_id = -1 if 0 in alt_codes else 0\n", + "model.initialize_graph(alternative_codes=alt_codes, root_id=root_id)\n", + "\n", + "model.utility_ca = linear_utility_from_spec(\n", + " spec,\n", + " x_col=\"Label\",\n", + " p_col=\"coefficient\",\n", + " ignore_x=(\"#\",),\n", + " x_validator=set(x_ca.columns),\n", + " expr_col=\"Expression\",\n", + ")\n", + "apply_coefficients(coefficients, model)\n", + "model.choice_co_code = choice_column\n", + "model.availability_any = True\n", + "model.set_cap(50)\n", + "\n", + "model.required_data()" + ] + }, + { + "cell_type": "markdown", + "id": "353a1429", + "metadata": {}, + "source": [ + "## Review and diagnose the model" + ] + }, + { + "cell_type": "code", + "execution_count": 260, + "id": "69b71ce3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
<empty>
" + ], + "text/plain": [ + "dictx()" + ] + }, + "execution_count": 260, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model, problems = model.doctor()\n", + "problems" + ] + }, + { + "cell_type": "markdown", + "id": "775a2667", + "metadata": {}, + "source": [ + "## Estimate" + ] + }, + { + "cell_type": "code", + "execution_count": 261, + "id": "6dca5930", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "

Iteration 018 [Optimization terminated successfully]

" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "

Best LL = -91.7785059701134

" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "

...

" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
keyvalue
loglikenp.float64(-91.7785059701134)
x\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
0
coef_ivt_auto-0.080334
coef_ivt_transit-0.038466
coef_lot_capacity0.493467
coef_wait_transit-0.035961
coef_walk_transit-0.049183
tolerancenp.float64(7.158925585950065e-06)
steps
array([1. , 1. , 1. , 1. , 1. , 1. , 0.5, 1. , 1. , 0.5, 1. , 1. , 1. ,\n",
+       "       0.5, 1. , 1. , 1. , 0.5])
message'Optimization terminated successfully'
elapsed_time0:00:00.207510
method'BHHH'
n_cases39
iteration_number18
" + ], + "text/plain": [ + "┣ loglike: np.float64(-91.7785059701134)\n", + "┣ x: coef_ivt_auto -0.080334\n", + "┃ coef_ivt_transit -0.038466\n", + "┃ coef_lot_capacity 0.493467\n", + "┃ coef_wait_transit -0.035961\n", + "┃ coef_walk_transit -0.049183\n", + "┃ dtype: float64\n", + "┣ tolerance: np.float64(7.158925585950065e-06)\n", + "┣ steps: array([1. , 1. , 1. , 1. , 1. , 1. , 0.5, 1. , 1. , 0.5, 1. , 1. , 1. ,\n", + "┃ 0.5, 1. , 1. , 1. , 0.5])\n", + "┣ message: 'Optimization terminated successfully'\n", + "┣ elapsed_time: datetime.timedelta(microseconds=207510)\n", + "┣ method: 'BHHH'\n", + "┣ n_cases: 39\n", + "┣ iteration_number: 18" + ] + }, + "execution_count": 261, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.estimate(method=\"BHHH\", options={\"maxiter\": 1000})" + ] + }, + { + "cell_type": "code", + "execution_count": 262, + "id": "be2c068f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
StatisticAggregatePer Case
Number of Cases39
Log Likelihood at Convergence-91.78-2.35
Log Likelihood at Null Parameters-194.63-4.99
Rho Squared w.r.t. Null Parameters0.528
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 262, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.parameter_summary()\n", + "model.estimation_statistics()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f6cfc06", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ba7d6d28", + "metadata": {}, + "source": [ + "## Write estimation results" + ] + }, + { + "cell_type": "code", + "execution_count": 263, + "id": "3a66df6b", + "metadata": {}, + "outputs": [], + "source": [ + "result_dir = EDB_DIRECTORY / \"estimated\"\n", + "data = SimpleNamespace(edb_directory=EDB_DIRECTORY, coefficients=coefficients)\n", + "\n", + "update_coefficients(\n", + " model,\n", + " data,\n", + " result_dir,\n", + " output_file=f\"{modelname}_coefficients.csv\",\n", + ")\n", + "\n", + "model.to_xlsx(\n", + " result_dir / f\"{modelname}_model_estimation.xlsx\",\n", + " data_statistics=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 264, + "id": "be5ddd94", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 ValueStd Errt StatSignifNull Value
Parameter     
coef_ivt_auto-0.0803 0.0122-6.59*** 0.00
coef_ivt_transit-0.0385 0.00917-4.20*** 0.00
coef_lot_capacity 0.493 0.179 2.76** 0.00
coef_wait_transit-0.0360 0.0173-2.07* 0.00
coef_walk_transit-0.0492 0.0212-2.32* 0.00
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 264, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.parameter_summary()" + ] + }, + { + "cell_type": "markdown", + "id": "484b9444", + "metadata": {}, + "source": [] + }, + { + "cell_type": "markdown", + "id": "13cd60ff", + "metadata": {}, + "source": [ + "## Next steps\n", + "\n", + "Review the revised coefficient file, then copy `park_and_ride_lot_choice_coefficients.csv` into the active configuration directory before running ActivitySim in simulation mode." + ] + }, + { + "cell_type": "code", + "execution_count": 265, + "id": "26f1079d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
coefficient_namevalueconstrain
0coef_zero0.000000T
1coef_unavailable-999.000000F
2coef_ivt_auto-0.080334F
3coef_ivt_transit-0.038466F
4coef_auto_op_costs0.000000F
5coef_walk_transit-0.049183F
6coef_wait_transit-0.035961F
7coef_xfer_transit0.000000F
8coef_xwait_transit0.000000F
9coef_small_lot0.000000F
10coef_medium_lot0.000000F
11coef_detour_dist0.000000F
12coef_percent_drive0.000000F
13coef_lot_capacity0.493467F
14coef_toll_auto0.000000F
\n", + "
" + ], + "text/plain": [ + " coefficient_name value constrain\n", + "0 coef_zero 0.000000 T\n", + "1 coef_unavailable -999.000000 F\n", + "2 coef_ivt_auto -0.080334 F\n", + "3 coef_ivt_transit -0.038466 F\n", + "4 coef_auto_op_costs 0.000000 F\n", + "5 coef_walk_transit -0.049183 F\n", + "6 coef_wait_transit -0.035961 F\n", + "7 coef_xfer_transit 0.000000 F\n", + "8 coef_xwait_transit 0.000000 F\n", + "9 coef_small_lot 0.000000 F\n", + "10 coef_medium_lot 0.000000 F\n", + "11 coef_detour_dist 0.000000 F\n", + "12 coef_percent_drive 0.000000 F\n", + "13 coef_lot_capacity 0.493467 F\n", + "14 coef_toll_auto 0.000000 F" + ] + }, + "execution_count": 265, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.read_csv(result_dir / f\"{modelname}_coefficients.csv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 266, + "id": "cc467ed6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Chosen Alt MeanAll Alts MeanDifference
Variable
util_drive_time35.137123112.517128-77.380005
util_total_wait32.39861359.803665-27.405052
util_walk_time25.22151941.669800-16.448280
util_ivtt56.971474120.209511-63.238037
util_log_lot_capacity6.1967385.1871291.009609
\n", + "
" + ], + "text/plain": [ + " Chosen Alt Mean All Alts Mean Difference\n", + "Variable \n", + "util_drive_time 35.137123 112.517128 -77.380005\n", + "util_total_wait 32.398613 59.803665 -27.405052\n", + "util_walk_time 25.221519 41.669800 -16.448280\n", + "util_ivtt 56.971474 120.209511 -63.238037\n", + "util_log_lot_capacity 6.196738 5.187129 1.009609" + ] + }, + "execution_count": 266, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Compare mean predictor values for the chosen alternative vs. all alternatives\n", + "predictor_cols = [col for col in dict.fromkeys(spec[\"Label\"]) if col in x_ca.columns]\n", + "\n", + "chosen_by_chooser = x_co[choice_column].to_dict()\n", + "alt_ids = x_ca.index.get_level_values(alternative_id_column)\n", + "chooser_ids = x_ca.index.get_level_values(chooser_id_column)\n", + "is_chosen = alt_ids == chooser_ids.map(chosen_by_chooser)\n", + "\n", + "comparison = pd.DataFrame(\n", + " {\n", + " \"Chosen Alt Mean\": x_ca.loc[is_chosen, predictor_cols].mean(),\n", + " \"All Alts Mean\": x_ca[predictor_cols].mean(),\n", + " }\n", + ")\n", + "comparison[\"Difference\"] = comparison[\"Chosen Alt Mean\"] - comparison[\"All Alts Mean\"]\n", + "comparison.index.name = \"Variable\"\n", + "comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 267, + "id": "be8514ac", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
util_drive_timeutil_total_waitutil_walk_timeutil_ivttutil_log_lot_capacity
tour_idpnr_zone_id
92505006623618.45908950.63047032.576805111.6475377.733684
41837616623616.66146712.91935513.617260116.2808697.733684
48721106624165.95155311.8347584.9893944.9948126.904751
38385006624262.11502544.71034619.76447591.4646996.456770
112513006624833.67374026.78571311.51956039.7726825.780744
18992006626022.32558622.00000019.93128039.9177135.278115
61258906626813.67685118.82376922.27482085.1188206.003887
146128906627629.42906214.97041479.7499629.9898686.104793
31538006627629.02022949.26235215.98037975.5919886.104793
40020576628113.005601130.00000028.56836395.4672477.313887
77999616628320.82269310.75836718.66214444.3049557.387090
29578206628322.77879068.88328629.06554885.7426767.387090
10099486628323.93223019.14638322.06671057.6207207.387090
70373616628532.3382955.03574713.30697820.9386253.951244
59044876628564.53372253.4375008.51596160.0328603.951244
6942106628728.04236632.32775110.93482038.3353046.666957
2141746628711.11265112.50000014.79068029.1417776.666957
90368726628719.34776921.25000011.16944061.9364056.666957
117642106628935.73001917.00211111.5504596.5521256.154858
113870516628968.32162539.44195972.30638138.4869926.154858
11612100662915.73337382.50000040.17838337.9764255.934894
30795846630041.9797029.63287437.4437527.9967215.398163
133628006630328.26457219.00000024.97772030.5288704.025352
68938206630330.72903117.28260837.51629322.6041154.025352
5330874663047.60724326.00000027.07579088.8222816.021023
5979517663047.46683718.06976720.48982030.5326756.021023
36999616630533.95784011.59090911.87053324.4256297.275865
21419206630513.5087368.00000015.62184035.2300007.275865
148146106630617.03892912.51657938.48493253.3959506.216606
89192206631359.60345524.58532736.93319745.6828545.560682
992784366313209.95127962.92105151.857876111.6820375.560682
96568106631515.56786720.28260811.59906062.5255667.548029
110868906633421.83702546.50000045.19903970.0000005.236442
61066096633452.69455374.00000029.649759127.7894745.236442
1604820663388.04030619.54761911.65601756.2813955.313206
103287826635291.60607935.25000029.09987470.3625186.927558
126252106635710.56673822.64629612.82751846.9823616.908755
104317516636341.32253382.50000019.86190880.0000006.340359
72083286638041.5932779.00000019.954599105.7300037.057037
\n", + "
" + ], + "text/plain": [ + " util_drive_time util_total_wait util_walk_time \\\n", + "tour_id pnr_zone_id \n", + "9250500 66236 18.459089 50.630470 32.576805 \n", + "4183761 66236 16.661467 12.919355 13.617260 \n", + "4872110 66241 65.951553 11.834758 4.989394 \n", + "3838500 66242 62.115025 44.710346 19.764475 \n", + "11251300 66248 33.673740 26.785713 11.519560 \n", + "1899200 66260 22.325586 22.000000 19.931280 \n", + "6125890 66268 13.676851 18.823769 22.274820 \n", + "14612890 66276 29.429062 14.970414 79.749962 \n", + "3153800 66276 29.020229 49.262352 15.980379 \n", + "4002057 66281 13.005601 130.000000 28.568363 \n", + "7799961 66283 20.822693 10.758367 18.662144 \n", + "2957820 66283 22.778790 68.883286 29.065548 \n", + "1009948 66283 23.932230 19.146383 22.066710 \n", + "7037361 66285 32.338295 5.035747 13.306978 \n", + "5904487 66285 64.533722 53.437500 8.515961 \n", + "694210 66287 28.042366 32.327751 10.934820 \n", + "214174 66287 11.112651 12.500000 14.790680 \n", + "9036872 66287 19.347769 21.250000 11.169440 \n", + "11764210 66289 35.730019 17.002111 11.550459 \n", + "11387051 66289 68.321625 39.441959 72.306381 \n", + "11612100 66291 5.733373 82.500000 40.178383 \n", + "3079584 66300 41.979702 9.632874 37.443752 \n", + "13362800 66303 28.264572 19.000000 24.977720 \n", + "6893820 66303 30.729031 17.282608 37.516293 \n", + "5330874 66304 7.607243 26.000000 27.075790 \n", + "5979517 66304 7.466837 18.069767 20.489820 \n", + "3699961 66305 33.957840 11.590909 11.870533 \n", + "2141920 66305 13.508736 8.000000 15.621840 \n", + "14814610 66306 17.038929 12.516579 38.484932 \n", + "8919220 66313 59.603455 24.585327 36.933197 \n", + "9927843 66313 209.951279 62.921051 51.857876 \n", + "9656810 66315 15.567867 20.282608 11.599060 \n", + "11086890 66334 21.837025 46.500000 45.199039 \n", + "6106609 66334 52.694553 74.000000 29.649759 \n", + "1604820 66338 8.040306 19.547619 11.656017 \n", + "10328782 66352 91.606079 35.250000 29.099874 \n", + "12625210 66357 10.566738 22.646296 12.827518 \n", + "10431751 66363 41.322533 82.500000 19.861908 \n", + "7208328 66380 41.593277 9.000000 19.954599 \n", + "\n", + " util_ivtt util_log_lot_capacity \n", + "tour_id pnr_zone_id \n", + "9250500 66236 111.647537 7.733684 \n", + "4183761 66236 116.280869 7.733684 \n", + "4872110 66241 4.994812 6.904751 \n", + "3838500 66242 91.464699 6.456770 \n", + "11251300 66248 39.772682 5.780744 \n", + "1899200 66260 39.917713 5.278115 \n", + "6125890 66268 85.118820 6.003887 \n", + "14612890 66276 9.989868 6.104793 \n", + "3153800 66276 75.591988 6.104793 \n", + "4002057 66281 95.467247 7.313887 \n", + "7799961 66283 44.304955 7.387090 \n", + "2957820 66283 85.742676 7.387090 \n", + "1009948 66283 57.620720 7.387090 \n", + "7037361 66285 20.938625 3.951244 \n", + "5904487 66285 60.032860 3.951244 \n", + "694210 66287 38.335304 6.666957 \n", + "214174 66287 29.141777 6.666957 \n", + "9036872 66287 61.936405 6.666957 \n", + "11764210 66289 6.552125 6.154858 \n", + "11387051 66289 38.486992 6.154858 \n", + "11612100 66291 37.976425 5.934894 \n", + "3079584 66300 7.996721 5.398163 \n", + "13362800 66303 30.528870 4.025352 \n", + "6893820 66303 22.604115 4.025352 \n", + "5330874 66304 88.822281 6.021023 \n", + "5979517 66304 30.532675 6.021023 \n", + "3699961 66305 24.425629 7.275865 \n", + "2141920 66305 35.230000 7.275865 \n", + "14814610 66306 53.395950 6.216606 \n", + "8919220 66313 45.682854 5.560682 \n", + "9927843 66313 111.682037 5.560682 \n", + "9656810 66315 62.525566 7.548029 \n", + "11086890 66334 70.000000 5.236442 \n", + "6106609 66334 127.789474 5.236442 \n", + "1604820 66338 56.281395 5.313206 \n", + "10328782 66352 70.362518 6.927558 \n", + "12625210 66357 46.982361 6.908755 \n", + "10431751 66363 80.000000 6.340359 \n", + "7208328 66380 105.730003 7.057037 " + ] + }, + "execution_count": 267, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_ca.loc[is_chosen, predictor_cols]" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "activitysim (3.10.19)", + "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.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}