From 16620d5feb5f46cdc9e417a8946daf4b83f788da Mon Sep 17 00:00:00 2001 From: Fletcher Foti Date: Tue, 31 Mar 2015 16:31:26 -0700 Subject: [PATCH 1/2] school location is working for the three segments (and I also now identify which persons make which school choices) --- activitysim/defaults/misc.py | 2 +- activitysim/defaults/models/__init__.py | 1 + activitysim/defaults/models/auto_ownership.py | 3 - .../defaults/models/school_location.py | 53 ++++++++++++ .../defaults/models/workplace_location.py | 5 +- activitysim/defaults/tables/persons.py | 30 ++++--- .../configs/destination_choice_size_terms.csv | 4 +- example/configs/school_location.csv | 9 +++ example/configs/settings.yaml | 6 +- example/simulation.ipynb | 81 ++++++++++++++++--- 10 files changed, 164 insertions(+), 30 deletions(-) create mode 100644 activitysim/defaults/models/school_location.py create mode 100644 example/configs/school_location.csv diff --git a/activitysim/defaults/misc.py b/activitysim/defaults/misc.py index c4ed07477..b4040adaf 100644 --- a/activitysim/defaults/misc.py +++ b/activitysim/defaults/misc.py @@ -25,7 +25,7 @@ def data_dir(): return '.' -@sim.injectable(cache=True) +@sim.injectable() def settings(configs_dir): with open(os.path.join(configs_dir, "configs", "settings.yaml")) as f: return yaml.load(f) diff --git a/activitysim/defaults/models/__init__.py b/activitysim/defaults/models/__init__.py index 1339f6c1a..076248d01 100644 --- a/activitysim/defaults/models/__init__.py +++ b/activitysim/defaults/models/__init__.py @@ -8,5 +8,6 @@ import non_mandatory_tour_frequency import mandatory_scheduling import non_mandatory_scheduling +import school_location import workplace_location import mode diff --git a/activitysim/defaults/models/auto_ownership.py b/activitysim/defaults/models/auto_ownership.py index e0bd2abf6..f970b40e7 100644 --- a/activitysim/defaults/models/auto_ownership.py +++ b/activitysim/defaults/models/auto_ownership.py @@ -7,9 +7,6 @@ with given characteristics owns """ -# this is the max number of cars allowable in the auto ownership model -MAX_NUM_CARS = 5 - @sim.injectable() def auto_ownership_spec(configs_dir): diff --git a/activitysim/defaults/models/school_location.py b/activitysim/defaults/models/school_location.py new file mode 100644 index 000000000..785da2603 --- /dev/null +++ b/activitysim/defaults/models/school_location.py @@ -0,0 +1,53 @@ +import os +import pandas as pd +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim + + +""" +The school location model predicts the zones in which various people will +go to school. +""" + + +@sim.table() +def school_location_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', "school_location.csv") + return asim.read_model_spec(f).fillna(0) + + +@sim.model() +def school_location_simulate(set_random_seed, + persons_merged, + school_location_spec, + skims, + destination_size_terms): + + choosers = persons_merged.to_frame() + alternatives = destination_size_terms.to_frame() + spec = school_location_spec.to_frame() + + # set the keys for this lookup - in this case there is a TAZ in the choosers + # and a TAZ in the alternatives which get merged during interaction + skims.set_keys("TAZ", "TAZ_r") + # the skims will be available under the name "skims" for any @ expressions + locals_d = {"skims": skims} + + choices_list = [] + for school_type in ['university', 'highschool', 'gradeschool']: + + locals_d['segment'] = school_type + + choices, _ = asim.interaction_simulate(choosers[choosers["is_" + + school_type]], + alternatives, + spec[[school_type]], + skims=skims, + locals_d=locals_d) + choices_list.append(choices) + + choices = pd.concat(choices_list) + choices = choices.reindex(persons_merged.index).fillna(-1).astype('int') + + print "Describe of choices:\n", choices.describe() + sim.add_column("persons", "school_taz", choices) diff --git a/activitysim/defaults/models/workplace_location.py b/activitysim/defaults/models/workplace_location.py index 766b6f76c..1e706164a 100644 --- a/activitysim/defaults/models/workplace_location.py +++ b/activitysim/defaults/models/workplace_location.py @@ -15,8 +15,6 @@ def workplace_location_spec(configs_dir): return asim.read_model_spec(f).fillna(0) -# FIXME there are three school models that go along with this one which have -# FIXME not been implemented yet @sim.model() def workplace_location_simulate(set_random_seed, persons_merged, @@ -25,6 +23,7 @@ def workplace_location_simulate(set_random_seed, destination_size_terms): choosers = persons_merged.to_frame() + choosers = choosers[choosers.employed_cat.isin(["full", "part"])] alternatives = destination_size_terms.to_frame() # set the keys for this lookup - in this case there is a TAZ in the choosers @@ -39,5 +38,7 @@ def workplace_location_simulate(set_random_seed, skims=skims, locals_d=locals_d) + choices = choices.reindex(persons_merged.index).fillna(-1).astype('int') + print "Describe of choices:\n", choices.describe() sim.add_column("persons", "workplace_taz", choices) diff --git a/activitysim/defaults/tables/persons.py b/activitysim/defaults/tables/persons.py index 8dbdaaeb7..1988c8e5d 100644 --- a/activitysim/defaults/tables/persons.py +++ b/activitysim/defaults/tables/persons.py @@ -95,9 +95,6 @@ def female(persons): # count the number of mandatory tours for each person @sim.column("persons") def num_mand(persons): - # FIXME this is really because we ask for ALL columns in the persons data - # FIXME frame - urbansim actually only asks for the columns that are used by - # FIXME the model specs in play at that time if "mandatory_tour_frequency" not in persons.columns: return pd.Series(0, index=persons.index) @@ -146,7 +143,7 @@ def student_is_employed(persons): @sim.column("persons") def nonstudent_to_school(persons): return (persons.ptype_cat.isin(['full', 'part', 'nonwork', 'retired']) & - persons.student_cat.isin(['high', 'college'])) + persons.student_cat.isin(['grade_or_high', 'college'])) @sim.column("persons") @@ -162,14 +159,28 @@ def is_worker(persons): @sim.column("persons") def is_student(persons): - return persons.student_cat.isin(['high', 'college']) + return persons.student_cat.isin(['grade_or_high', 'college']) + + +@sim.column("persons") +def is_gradeschool(persons, settings): + return (persons.student_cat == "grade_or_high") & \ + (persons.age <= settings['grade_school_max_age']) + + +@sim.column("persons") +def is_highschool(persons, settings): + return (persons.student_cat == "grade_or_high") & \ + (persons.age > settings['grade_school_max_age']) + + +@sim.column("persons") +def is_university(persons): + return persons.student_cat == "university" @sim.column("persons") def workplace_taz(persons): - # FIXME this is really because we ask for ALL columns in the persons data - # FIXME frame - urbansim actually only asks for the columns that are used by - # FIXME the model specs in play at that time return pd.Series(1, persons.index) @@ -181,8 +192,7 @@ def home_taz(households, persons): @sim.column("persons") def school_taz(persons): - # FIXME need to fix this after getting school lcm working - return persons.workplace_taz + return pd.Series(1, persons.index) # this use the distance skims to compute the raw distance to work from home diff --git a/example/configs/destination_choice_size_terms.csv b/example/configs/destination_choice_size_terms.csv index 187dc127c..07c136f71 100644 --- a/example/configs/destination_choice_size_terms.csv +++ b/example/configs/destination_choice_size_terms.csv @@ -4,8 +4,8 @@ segment,TOTHH,RETEMPN,FPSEMPN,HEREMPN,OTHEMPN,AGREMPN,MWTEMPN,AGE0519,HSENROLL,C "work, high",0,0.11,0.207,0.284,0.154,0.006,0.239,0,0,0,0 "work, veryhigh",0,0.093,0.27,0.241,0.146,0.004,0.246,0,0,0,0 university,0,0,0,0,0,0,0,0,0,0.592,0.408 -"school, grade",0,0,0,0,0,0,0,1,0,0,0 -"school, high",0,0,0,0,0,0,0,0,1,0,0 +gradeschool,0,0,0,0,0,0,0,1,0,0,0 +highschool,0,0,0,0,0,0,0,0,1,0,0 "escort, kids",0,0.225,0,0.144,0,0,0,0.465,0.166,0,0 "escort, no kids",0,0.225,0,0.144,0,0,0,0.465,0.166,0,0 shopping,0,1,0,0,0,0,0,0,0,0,0 diff --git a/example/configs/school_location.csv b/example/configs/school_location.csv new file mode 100644 index 000000000..e7cfea31e --- /dev/null +++ b/example/configs/school_location.csv @@ -0,0 +1,9 @@ +Description,Expression,university,highschool,gradeschool +"Distance, piecewise linear from 0 to 1 miles",@skims['DISTANCE'].clip(1),-3.2451,-0.9523,-1.6419 +"Distance, piecewise linear from 1 to 2 miles","@(skims['DISTANCE']-1).clip(0,1)",-2.7011,-0.5700,-0.5700 +"Distance, piecewise linear from 2 to 5 miles","@(skims['DISTANCE']-2).clip(0,3)",-0.5707,-0.5700,-0.5700 +"Distance, piecewise linear from 5 to 15 miles","@(skims['DISTANCE']-5).clip(0,10)",-0.5002,-0.1930,-0.2031 +"Distance, piecewise linear for 15+ miles",@(skims['DISTANCE']-15.0).clip(0),-0.0730,-0.1882,-0.0460 +Mode choice logsum,mode_choice_logsums,0.5358,0.5358,0.5358 +Size variable,@df[segment].apply(np.log1p),1.0000,1.0000,1.0000 +No attractions,@df[segment]==0,-999.0000,-999.0000,-999.0000 diff --git a/example/configs/settings.yaml b/example/configs/settings.yaml index 7a248d1b0..86498dbf7 100644 --- a/example/configs/settings.yaml +++ b/example/configs/settings.yaml @@ -7,6 +7,8 @@ rural_threshold: 6 households_sample_size: 1000 +grade_school_max_age: 14 + county_map: San Francisco: 1 San Mateo: 2 @@ -25,8 +27,8 @@ employment_map: 4: child student_map: - 1: high - 2: college + 1: grade_or_high + 2: university 3: not person_type_map: diff --git a/example/simulation.ipynb b/example/simulation.ipynb index bb36f46ae..2f90b8b68 100644 --- a/example/simulation.ipynb +++ b/example/simulation.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:880950d73f4f9e461598c60051b1f421518aa82880440b1f17bdf1ae89f0bc48" + "signature": "sha256:8dd6ed7b0367358850955b8044ce5cd4396e31fd6b83bd444987c950b7c3696a" }, "nbformat": 3, "nbformat_minor": 0, @@ -22,6 +22,67 @@ "outputs": [], "prompt_number": 1 }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"school_location_simulate\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'school_location_simulate'\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['mode_choice_logsums']\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['mode_choice_logsums']\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['mode_choice_logsums']\n", + "Describe of choices:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "count 2538.000000\n", + "mean 190.435776\n", + "std 389.915126\n", + "min -1.000000\n", + "25% -1.000000\n", + "50% -1.000000\n", + "75% 69.000000\n", + "max 1450.000000\n", + "Name: TAZ, dtype: float64\n", + "Time to execute model 'school_location_simulate': 18.74s\n", + "Total time to execute: 18.74s\n" + ] + } + ], + "prompt_number": 2 + }, { "cell_type": "code", "collapsed": false, @@ -51,17 +112,17 @@ "output_type": "stream", "stream": "stdout", "text": [ - "count 2546.000000\n", - "mean 775.958759\n", - "std 425.999370\n", - "min 1.000000\n", - "25% 418.000000\n", - "50% 776.500000\n", - "75% 1168.000000\n", + "count 2538.000000\n", + "mean 332.508668\n", + "std 473.007494\n", + "min -1.000000\n", + "25% -1.000000\n", + "50% -1.000000\n", + "75% 651.000000\n", "max 1452.000000\n", "Name: TAZ, dtype: float64\n", - "Time to execute model 'workplace_location_simulate': 20.54s\n", - "Total time to execute: 20.54s\n" + "Time to execute model 'workplace_location_simulate': 10.24s\n", + "Total time to execute: 10.24s\n" ] } ], From 786ddd8a5cd824f3b292ad44948aa0394dc6c130 Mon Sep 17 00:00:00 2001 From: Fletcher Foti Date: Wed, 1 Apr 2015 14:19:30 -0700 Subject: [PATCH 2/2] need to mode grade school age to test --- activitysim/defaults/test/configs/settings.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/activitysim/defaults/test/configs/settings.yaml b/activitysim/defaults/test/configs/settings.yaml index 7a248d1b0..68da70d94 100644 --- a/activitysim/defaults/test/configs/settings.yaml +++ b/activitysim/defaults/test/configs/settings.yaml @@ -7,6 +7,8 @@ rural_threshold: 6 households_sample_size: 1000 +grade_school_max_age: 14 + county_map: San Francisco: 1 San Mateo: 2