diff --git a/activitysim/abm/models/location_choice.py b/activitysim/abm/models/location_choice.py index 937721c05b..6b11f8522c 100644 --- a/activitysim/abm/models/location_choice.py +++ b/activitysim/abm/models/location_choice.py @@ -833,6 +833,24 @@ def run_location_choice( ) state.tracing.trace_df(choices_df, estimation_trace_label) + if want_logsums & (not skip_choice): + # grabbing index, could be person_id or proto_person_id + index_name = choices_df.index.name + # merging mode choice logsum of chosen alternative to choices + choices_df = ( + pd.merge( + choices_df.reset_index(), + location_sample_df.reset_index()[ + [index_name, model_settings.ALT_DEST_COL_NAME, ALT_LOGSUM] + ], + how="left", + left_on=[index_name, "choice"], + right_on=[index_name, model_settings.ALT_DEST_COL_NAME], + ) + .drop(columns=model_settings.ALT_DEST_COL_NAME) + .set_index(index_name) + ) + choices_list.append(choices_df) if want_sample_table: @@ -850,7 +868,7 @@ def run_location_choice( else: # this will only happen with small samples (e.g. singleton) with no (e.g.) school segs logger.warning("%s no choices", trace_label) - choices_df = pd.DataFrame(columns=["choice", "logsum"]) + choices_df = pd.DataFrame(columns=["choice", "logsum", ALT_LOGSUM]) if len(sample_list) > 0: save_sample_df = pd.concat(sample_list) @@ -893,7 +911,8 @@ def iterate_location_choice( Returns ------- adds choice column model_settings['DEST_CHOICE_COLUMN_NAME'] - adds logsum column model_settings['DEST_CHOICE_LOGSUM_COLUMN_NAME']- if provided + adds destination choice logsum column model_settings['DEST_CHOICE_LOGSUM_COLUMN_NAME']- if provided + adds mode choice logsum to selected destination column model_settings['MODE_CHOICE_LOGSUM_COLUMN_NAME']- if provided adds annotations to persons table """ @@ -903,7 +922,11 @@ def iterate_location_choice( chooser_filter_column = model_settings.CHOOSER_FILTER_COLUMN_NAME dest_choice_column_name = model_settings.DEST_CHOICE_COLUMN_NAME - logsum_column_name = model_settings.DEST_CHOICE_LOGSUM_COLUMN_NAME + dc_logsum_column_name = model_settings.DEST_CHOICE_LOGSUM_COLUMN_NAME + mc_logsum_column_name = model_settings.MODE_CHOICE_LOGSUM_COLUMN_NAME + want_logsums = (dc_logsum_column_name is not None) | ( + mc_logsum_column_name is not None + ) sample_table_name = model_settings.DEST_CHOICE_SAMPLE_TABLE_NAME want_sample_table = ( @@ -954,7 +977,7 @@ def iterate_location_choice( persons_merged_df_, network_los, shadow_price_calculator=spc, - want_logsums=logsum_column_name is not None, + want_logsums=want_logsums, want_sample_table=want_sample_table, estimator=estimator, model_settings=model_settings, @@ -1029,10 +1052,15 @@ def iterate_location_choice( ) # add the dest_choice_logsum column to persons dataframe - if logsum_column_name: - persons_df[logsum_column_name] = ( + if dc_logsum_column_name: + persons_df[dc_logsum_column_name] = ( choices_df["logsum"].reindex(persons_df.index).astype("float") ) + # add the mode choice logsum column to persons dataframe + if mc_logsum_column_name: + persons_df[mc_logsum_column_name] = ( + choices_df[ALT_LOGSUM].reindex(persons_df.index).astype("float") + ) if save_sample_df is not None: # might be None for tiny samples even if sample_table_name was specified @@ -1072,9 +1100,13 @@ def iterate_location_choice( if state.settings.trace_hh_id: state.tracing.trace_df(households_df, label=trace_label, warn_if_empty=True) - if logsum_column_name: + if dc_logsum_column_name: + tracing.print_summary( + dc_logsum_column_name, choices_df["logsum"], value_counts=True + ) + if mc_logsum_column_name: tracing.print_summary( - logsum_column_name, choices_df["logsum"], value_counts=True + mc_logsum_column_name, choices_df[ALT_LOGSUM], value_counts=True ) return persons_df diff --git a/activitysim/core/configuration/logit.py b/activitysim/core/configuration/logit.py index c01187eeb6..cb6cf04325 100644 --- a/activitysim/core/configuration/logit.py +++ b/activitysim/core/configuration/logit.py @@ -177,6 +177,9 @@ class TourLocationComponentSettings(LocationComponentSettings, extra="forbid"): CHOOSER_FILTER_COLUMN_NAME: str | None = None DEST_CHOICE_COLUMN_NAME: str | None = None DEST_CHOICE_LOGSUM_COLUMN_NAME: str | None = None + """Column name for logsum calculated across all sampled destinations.""" + MODE_CHOICE_LOGSUM_COLUMN_NAME: str | None = None + """Column name for logsum calculated across all sampled modes to selected destination.""" DEST_CHOICE_SAMPLE_TABLE_NAME: str | None = None CHOOSER_TABLE_NAME: str | None = None CHOOSER_SEGMENT_COLUMN_NAME: str | None = None