Repository navigation
Explicit Telecommute: new telework_arrangement and telework_duration components
#1126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
i-am-sijia
wants to merge
11
commits into
ActivitySim:main
Choose a base branch
from
wsp-sag:explicit-telecommute
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+5,755
−4
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3004fac
[skip ci] telework arrangement - initial
i-am-sijia 2451199
[skip ci] telework duration - initial
i-am-sijia 331144d
add to settings checker
i-am-sijia 6527695
add to init
i-am-sijia 9d3f61a
update util.py
i-am-sijia a2ecde1
unit tests for the two new components
i-am-sijia 54f7770
blacken
i-am-sijia a689658
add to larch models
i-am-sijia c7460e8
address copilot comments
i-am-sijia f92fda0
add documentation and estimation memo
i-am-sijia c98a7f0
add example estimation notebooks
i-am-sijia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| # ActivitySim | ||
| # See full license in LICENSE.txt. | ||
| from __future__ import annotations | ||
|
|
||
| import logging | ||
|
|
||
| import pandas as pd | ||
|
|
||
| from activitysim.core import ( | ||
| config, | ||
| estimation, | ||
| expressions, | ||
| simulate, | ||
| tracing, | ||
| workflow, | ||
| ) | ||
| from activitysim.core.configuration.logit import LogitComponentSettings | ||
|
|
||
| logger = logging.getLogger("activitysim") | ||
|
|
||
|
|
||
| class TeleworkArrangementSettings(LogitComponentSettings, extra="forbid"): | ||
| """ | ||
| Settings for the `telework_arrangement` component. | ||
| """ | ||
|
|
||
| CHOOSER_FILTER_COLUMN_NAME: str = "is_worker" | ||
| """Column name in the dataframe to represent worker.""" | ||
|
|
||
| HAS_IN_HOME_WORK_ACTIVITY_ALT: int = 0 | ||
| """The alternative index for having in-home work activity on the simulation day.""" | ||
|
|
||
|
|
||
| @workflow.step | ||
| def telework_arrangement( | ||
| state: workflow.State, | ||
| persons_merged: pd.DataFrame, | ||
| persons: pd.DataFrame, | ||
| model_settings: TeleworkArrangementSettings | None = None, | ||
| model_settings_file_name: str = "telework_arrangement.yaml", | ||
| trace_label: str = "telework_arrangement", | ||
| ) -> None: | ||
| """ | ||
| This model predicts the telework arrangement on the simulation day for all workers. | ||
| The alternatives are whether or not a worker has in-home telework activities on the simulation day: | ||
| The result is a new column in the persons table, "has_in_home_work_activity": True or False | ||
|
|
||
| Parameters | ||
| ---------- | ||
| state : workflow.State | ||
| persons_merged : DataFrame | ||
| This represents the 'choosers' table for this component. | ||
| persons : DataFrame | ||
| The original persons table is referenced so the telework arrangement column | ||
| can be appended to it. | ||
| model_settings : TeleworkArrangementSettings, optional | ||
| The settings used in this model component. If not provided, they are | ||
| loaded out of the configs directory YAML file referenced by | ||
| the `model_settings_file_name` argument. | ||
| model_settings_file_name : str, default "telework_arrangement.yaml" | ||
| This is where model setting are found if `model_settings` is not given | ||
| explicitly. The same filename is also used to write settings files to | ||
| the estimation data bundle in estimation mode. | ||
| trace_label : str, default "telework_arrangement" | ||
| This label is used for various tracing purposes. | ||
| """ | ||
|
|
||
| if model_settings is None: | ||
| model_settings = TeleworkArrangementSettings.read_settings_file( | ||
| state.filesystem, | ||
| model_settings_file_name, | ||
| ) | ||
|
|
||
| chooser_filter_column_name = model_settings.CHOOSER_FILTER_COLUMN_NAME | ||
| choosers = persons_merged[persons_merged[chooser_filter_column_name]] | ||
|
|
||
| logger.info("Running %s with %d persons", trace_label, len(choosers)) | ||
|
|
||
| estimator = estimation.manager.begin_estimation(state, "telework_arrangement") | ||
|
|
||
| constants = config.get_model_constants(model_settings) | ||
|
|
||
| expressions.annotate_preprocessors( | ||
| state, | ||
| df=choosers, | ||
| locals_dict=constants, | ||
| skims=None, | ||
| model_settings=model_settings, | ||
| trace_label=trace_label, | ||
| ) | ||
|
|
||
| model_spec = state.filesystem.read_model_spec(file_name=model_settings.SPEC) | ||
| coefficients_df = state.filesystem.read_model_coefficients(model_settings) | ||
| model_spec = simulate.eval_coefficients( | ||
| state, model_spec, coefficients_df, estimator | ||
| ) | ||
| nest_spec = config.get_logit_model_settings(model_settings) | ||
|
|
||
| if estimator: | ||
| estimator.write_model_settings(model_settings, model_settings_file_name) | ||
| estimator.write_spec(model_settings) | ||
| estimator.write_coefficients(coefficients_df, model_settings) | ||
| estimator.write_choosers(choosers) | ||
|
|
||
| choices = simulate.simple_simulate( | ||
| state, | ||
| choosers=choosers, | ||
| spec=model_spec, | ||
| nest_spec=nest_spec, | ||
| locals_d=constants, | ||
| trace_label=trace_label, | ||
| trace_choice_name="telework_arrangement", | ||
| estimator=estimator, | ||
| compute_settings=model_settings.compute_settings, | ||
| ) | ||
|
|
||
| has_in_home_work_activity_alt = model_settings.HAS_IN_HOME_WORK_ACTIVITY_ALT | ||
| choices = choices == has_in_home_work_activity_alt | ||
|
|
||
| if estimator: | ||
| estimator.write_choices(choices) | ||
| choices = estimator.get_survey_values( | ||
| choices, | ||
| "persons", | ||
| "has_in_home_work_activity", | ||
| ) | ||
| estimator.write_override_choices(choices) | ||
| estimator.end_estimation() | ||
|
|
||
| persons["has_in_home_work_activity"] = ( | ||
| choices.reindex(persons.index).fillna(0).astype(bool) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like a value of 0 in this field indicates that a person has in-home work activities by default. So would this mean that people with null values are assumed to have in-home work activities? |
||
| ) | ||
|
|
||
| state.add_table("persons", persons) | ||
|
|
||
| tracing.print_summary( | ||
| "telework_arrangement.has_in_home_work_activity", | ||
| persons.has_in_home_work_activity, | ||
| value_counts=True, | ||
| ) | ||
|
|
||
| if state.settings.trace_hh_id: | ||
| state.tracing.trace_df(persons, label=trace_label, warn_if_empty=True) | ||
|
|
||
| expressions.annotate_tables( | ||
| state, | ||
| locals_dict=constants, | ||
| skims=None, | ||
| model_settings=model_settings, | ||
| trace_label=trace_label, | ||
| ) | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a general ActivitySim comment: I've noticed that in some model components (such as this one) the name(s) of the column with the choice is(are) hardcoded, but in others (such as telework duration in this PR) the name(s) is(are) defined in the model settings. Should this be consistent?