Skip to content

Commit

Permalink
Merge pull request #790 from ActivitySim/veh_type_alts_filter_fix
Browse files Browse the repository at this point in the history
Vehicle Type Alts Filtering Bug Fix
  • Loading branch information
jpn-- authored Feb 9, 2024
2 parents bdc9cac + 3521c8d commit a2ad2a1
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
59 changes: 59 additions & 0 deletions activitysim/abm/models/util/test/test_vehicle_type_alts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ActivitySim
# See full license in LICENSE.txt.

import pandas as pd
import pandas.testing as pdt

from activitysim.abm.models.vehicle_type_choice import (
get_combinatorial_vehicle_alternatives,
construct_model_alternatives,
VehicleTypeChoiceSettings,
)
from activitysim.core import workflow


def test_vehicle_type_alts():
state = workflow.State.make_default(__file__)

alts_cats_dict = {
"body_type": ["Car", "SUV"],
"fuel_type": ["Gas", "BEV"],
"age": [1, 2, 3],
}

alts_wide, alts_long = get_combinatorial_vehicle_alternatives(alts_cats_dict)

# alts are initially constructed combinatorially
assert len(alts_long) == 12, "alts_long should have 12 rows"
assert len(alts_wide) == 12, "alts_wide should have 12 rows"

model_settings = VehicleTypeChoiceSettings.model_construct()
model_settings.combinatorial_alts = alts_cats_dict
model_settings.PROBS_SPEC = None
model_settings.WRITE_OUT_ALTS_FILE = False

# constructing veh type data with missing alts
vehicle_type_data = pd.DataFrame(
data={
"body_type": ["Car", "Car", "Car", "SUV", "SUV"],
"fuel_type": ["Gas", "Gas", "BEV", "Gas", "BEV"],
"age": ["1", "2", "3", "1", "2"],
"dummy_data": [1, 2, 3, 4, 5],
},
index=[0, 1, 2, 3, 4],
)

alts_wide, alts_long = construct_model_alternatives(
state, model_settings, alts_cats_dict, vehicle_type_data
)

# should only have alts left that are in the file
assert len(alts_long) == 5, "alts_long should have 5 rows"

# indexes need to be the same to choices match alts
pdt.assert_index_equal(alts_long.index, alts_wide.index)

# columns need to be in correct order for downstream configs
pdt.assert_index_equal(
alts_long.columns, pd.Index(["body_type", "age", "fuel_type"])
)
18 changes: 15 additions & 3 deletions activitysim/abm/models/vehicle_type_choice.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,19 @@ def construct_model_alternatives(
), f"missing vehicle data for alternatives:\n {missing_alts}"
else:
# eliminate alternatives if no vehicle type data
num_alts_before_filer = len(alts_wide)
alts_wide = alts_wide[alts_wide._merge != "left_only"]
logger.warning(
f"Removed {num_alts_before_filer - len(alts_wide)} alternatives not included in input vehicle type data."
)
# need to also remove any alts from alts_long
alts_long.set_index(["body_type", "age", "fuel_type"], inplace=True)
alts_long = alts_long[
alts_long.index.isin(
alts_wide.set_index(["body_type", "age", "fuel_type"]).index
)
].reset_index()
alts_long.index = alts_wide.index
alts_wide.drop(columns="_merge", inplace=True)

# converting age to integer to allow interactions in utilities
Expand Down Expand Up @@ -455,11 +467,11 @@ def iterate_vehicle_type_choice(
alts = (
alts_long[alts_long.columns]
.apply(lambda row: "_".join(row.values.astype(str)), axis=1)
.values
.to_dict()
)
else:
alts = model_spec.columns
choices["vehicle_type"] = choices["vehicle_type"].map(dict(enumerate(alts)))
alts = enumerate(dict(model_spec.columns))
choices["vehicle_type"] = choices["vehicle_type"].map(alts)

# STEP II: append probabilistic vehicle type attributes
if probs_spec_file is not None:
Expand Down

0 comments on commit a2ad2a1

Please sign in to comment.