Skip to content

Commit 7401f5a

Browse files
authored
fix(estimation): correct the participant_num assignment logic for estimation mode in joint tour participation (#1008)
* fix(jtp): Correct the participant_num assignment logic for estimation mode in joint tour participation * fix(jtf): Handle missing PNUM column by selecting the first person in the household * style: blacken
1 parent 7e5202e commit 7401f5a

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

activitysim/abm/models/joint_tour_frequency.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,15 @@ def joint_tour_frequency(
137137
# - but we don't know the tour participants yet
138138
# - so we arbitrarily choose the first person in the household
139139
# - to be point person for the purpose of generating an index and setting origin
140-
temp_point_persons = persons.loc[persons.PNUM == 1]
140+
if "PNUM" in persons.columns:
141+
temp_point_persons = persons.loc[persons.PNUM == 1]
142+
else:
143+
# if PNUM is not available, we can still get the first person in the household
144+
temp_point_persons = (
145+
persons.sort_index() # ensure stable ordering
146+
.groupby("household_id", as_index=False)
147+
.first()
148+
)
141149
temp_point_persons["person_id"] = temp_point_persons.index
142150
temp_point_persons = temp_point_persons.set_index("household_id")
143151
temp_point_persons = temp_point_persons[["person_id", "home_zone_id"]]

activitysim/abm/models/joint_tour_participation.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -452,14 +452,24 @@ def joint_tour_participation(
452452
PARTICIPANT_COLS = ["tour_id", "household_id", "person_id"]
453453
participants = candidates[participate][PARTICIPANT_COLS].copy()
454454

455-
# assign participant_num
456-
# FIXME do we want something smarter than the participant with the lowest person_id?
457-
participants["participant_num"] = (
458-
participants.sort_values(by=["tour_id", "person_id"])
459-
.groupby("tour_id")
460-
.cumcount()
461-
+ 1
462-
)
455+
if estimator:
456+
# In estimation mode, use participant_num from survey data to preserve consistency
457+
# with the original survey data. ActivitySim treats participant_num=1 as the tour
458+
# leader, so the joint tour in the tour table will be associated with the tour
459+
# leader's person_id. We merge participant_num from survey data using the
460+
# participant_id as the join key to ensure the correct tour leader is identified.
461+
participants["participant_num"] = survey_participants_df.reindex(
462+
participants.index
463+
)["participant_num"]
464+
else:
465+
# assign participant_num
466+
# FIXME do we want something smarter than the participant with the lowest person_id?
467+
participants["participant_num"] = (
468+
participants.sort_values(by=["tour_id", "person_id"])
469+
.groupby("tour_id")
470+
.cumcount()
471+
+ 1
472+
)
463473

464474
state.add_table("joint_tour_participants", participants)
465475

0 commit comments

Comments
 (0)