<jupyter_start><jupyter_text>Exampville Mode ChoiceDiscrete choice modeling is at the heart of many transportion planning models.In this example, we will examine the development of a mode choice model for Exampville, an entirely fictional town built for the express purpose of demostrating the use of discrete choice modeling tools for transportation planning.<jupyter_code>skims = larch.OMX(larch.exampville.files.skims, mode='r')
skims
hh = pd.read_csv(larch.exampville.files.hh)
pp = pd.read_csv(larch.exampville.files.person)
tour = pd.read_csv(larch.exampville.files.tour)
hh.shape, pp.shape, tour.shape
hh.info()
pp.info()
tour.info()
tour.head()
# work (purpose=1) and non-work (purpose=2).
tour.TOURPURP.value_counts()
# Get only work trips
df = tour[tour.TOURPURP == 1]
df.shape
# Merge data
df = df.merge(hh, on="HHID").merge(pp, on=('HHID', 'PERSONID'))
df.shape
# For looking up data in the skims matrix using Larch, need zero-based numbering
df["HOMETAZi"] = df["HOMETAZ"] - 1
df["DTAZi"] = df["DTAZ"] - 1 
df.head().T
los_data = skims.get_rc_dataframe(df["HOMETAZi"], df["DTAZi"])
los_data
df = df.join(los_data)
df.shape<jupyter_output><empty_output><jupyter_text>Model definition<jupyter_code># Define numbers as names for modes
DA,SR,Walk,Bike,Transit = 1,2,3,4,5
dfs = larch.DataFrames(co=df, 
                       alt_codes=[DA,SR,Walk,Bike,Transit],
                       alt_names=['DA','SR','Walk','Bike','Transit'],
                       ch_name='TOUR_MODE')
# Define model
m = larch.Model(dataservice=dfs)
m.title = "Work Tour Mode Choice"
# Define Utility function
m.utility_co[DA] = P.InVehTime * X.AUTO_TIME + P.Cost * X.AUTO_COST
m.utility_co[SR] = (P.ASC_SR + P.InVehTime * X.AUTO_TIME 
                    + P.Cost * (X.AUTO_COST * 0.5) + P("LogIncome:SR") * X("log(INCOME)"))
m.utility_co[Walk] = (
        + P.ASC_Walk
        + P.NonMotorTime * X.WALK_TIME
        + P("LogIncome:Walk") * X("log(INCOME)")
)

m.utility_co[Bike] = (
        + P.ASC_Bike
        + P.NonMotorTime * X.BIKE_TIME
        + P("LogIncome:Bike") * X("log(INCOME)")
)

m.utility_co[Transit] = (
        + P.ASC_Transit
        + P.InVehTime * X.TRANSIT_IVTT
        + P.OutVehTime * X.TRANSIT_OVTT
        + P.Cost * X.TRANSIT_FARE
        + P("LogIncome:Transit") * X('log(INCOME)')
)
m.graph
# Nested logit model
Car = m.graph.new_node(parameter='Mu:Car', children=[DA,SR], name='Car')
NonMotor = m.graph.new_node(parameter='Mu:NonMotor', children=[Walk,Bike], name='NonMotor')
Motor = m.graph.new_node(parameter='Mu:Motor', children=[Car,Transit], name='Motor')
m.graph
m.choice_co_code = 'TOURMODE'
m.availability_co_vars = {
    DA: 'AGE >= 16',
    SR: 1,
    Walk: 'WALK_TIME < 60',
    Bike: 'BIKE_TIME < 60',
    Transit: 'TRANSIT_FARE>0',
}<jupyter_output><empty_output><jupyter_text>Model Estimation<jupyter_code>m.load_data()
m.dataframes.choice_avail_summary()
m.dataframes.data_co.statistics()
result = m.maximize_loglike(method='slsqp')
m.calculate_parameter_covariance()
m.parameter_summary()
m.estimation_statistics()<jupyter_output><empty_output><jupyter_text>Save and Report Model<jupyter_code>report = larch.Reporter(title=m.title)
report << '# Parameter Summary' << m.parameter_summary()
report.save(
    './exampville_mode_choice.html', 
    overwrite=True, 
    metadata=m,
)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1502994011976048, 'fraction_numerical': 0.005988023952095809, 'mean_word_length': 4.3456, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '619229', 'license': 'MIT', 'n_tokens_mistral': 1326, 'n_tokens_neox': 1290, 'n_words': 231, 'path': 'notebooks/31_larch_mode_choice.ipynb', 'repo_name': 'danhphan/discrete-choice-intro', 'size': '3340'}