diff --git a/.travis.yml b/.travis.yml index 02e1b80ec8..cc0f2232e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,8 +18,9 @@ install: - > conda create -q -c synthicity -n test-environment python=$TRAVIS_PYTHON_VERSION - numpy pandas pip pytables pytest urbansim + numpy pandas pip pytables pytest - source activate test-environment +- pip install https://github.com/synthicity/urbansim/archive/master.zip - pip install openmatrix - pip install pytest-cov coveralls pep8 - pip install . diff --git a/activitysim/activitysim.py b/activitysim/activitysim.py index 6148e20ab3..dbba87127e 100644 --- a/activitysim/activitysim.py +++ b/activitysim/activitysim.py @@ -14,13 +14,38 @@ def random_rows(df, n): def read_model_spec(fname, description_name="Description", - expression_name="Expression"): + expression_name="Expression", + stack=True): """ - Read in the excel file and reformat for machines + Read a CSV model specification into a Pandas DataFrame. + + The CSV is expected to have columns for component descriptions + and expressions, plus one or more alternatives. + + The CSV is required to have a header with column names. For example: + + Description,Expression,alt0,alt1,alt2 + + Parameters + ---------- + fname : str + Name of a CSV spec file. + description_name : str, optional + Name of the column in `fname` that contains the component description. + expression_name : str, optional + Name of the column in `fname` that contains the component expression. + + Returns + ------- + spec : pandas.DataFrame + The description column is dropped from the returned data and the + expression values are set as the table index. """ - cfg = pd.read_csv(fname) + cfg = pd.read_csv(fname, comment='#') # don't need description and set the expression to the index - cfg = cfg.drop(description_name, axis=1).set_index(expression_name).stack() + cfg = cfg.drop(description_name, axis=1).set_index(expression_name) + if stack: + cfg = cfg.stack() return cfg @@ -30,6 +55,38 @@ def identity_matrix(alt_names): index=alt_names) +def eval_variables(exprs, df): + """ + Evaluate a set of variable expressions from a spec in the context + of a given data table. + + There are two kinds of supported expressions: "simple" expressions are + evaluated in the context of the DataFrame using DataFrame.eval. + This is the default type of expression. + + Python expressions are evaluated in the context of this function using + Python's eval function. Because we use Python's eval this type of + expression supports more complex operations than a simple expression. + Python expressions are denoted by beginning with the @ character. + Users should take care that these expressions must result in + a Pandas Series. + + Parameters + ---------- + exprs : sequence of str + df : pandas.DataFrame + + Returns + ------- + variables : pandas.DataFrame + Will have the index of `df` and columns of `exprs`. + + """ + return pd.DataFrame.from_items( + [(e, eval(e[1:]) if e.startswith('@') else df.eval(e)) + for e in exprs]) + + def simple_simulate(choosers, alternatives, spec, skims=None, skim_join_name='zone_id', mult_by_alt_col=False, sample_size=None): @@ -87,13 +144,17 @@ def simple_simulate(choosers, alternatives, spec, df[skim_join_name+"_r"]) # evaluate the expressions to build the final matrix - vars = {} + vars = [] for expr in exprs: if expr[0][0] == "@": if mult_by_alt_col: expr = "({}) * df.{}".format(expr[0][1:], expr[1]) else: - expr = expr[0][1:] + if isinstance(expr, tuple): + expr = expr[0][1:] + else: + # it's already a string, but need to remove the "@" + expr = expr[1:] try: s = eval(expr) except Exception as e: @@ -103,21 +164,25 @@ def simple_simulate(choosers, alternatives, spec, if mult_by_alt_col: expr = "({}) * {}".format(*expr) else: - expr = expr[0] + if isinstance(expr, tuple): + expr = expr[0] + else: + # it's already a string, which is fine + pass try: s = df.eval(expr) except Exception as e: print "Failed with DataFrame eval:\n%s" % expr raise e - vars[expr] = s - vars[expr] = vars[expr].astype('float') # explicit cast - model_design = pd.DataFrame(vars, index=df.index) + vars.append((expr, s.astype('float'))) + model_design = pd.DataFrame.from_items(vars) + model_design.index = df.index df = random_rows(model_design, min(100000, len(model_design)))\ .describe().transpose() df = df[df["std"] == 0] if len(df): - print "WARNING: Describe of columns with no variability:\n", df + print "WARNING: Some columns have no variability:\n", df.index.values positions = mnl.mnl_simulate( model_design.as_matrix(), diff --git a/activitysim/cdap/__init__.py b/activitysim/cdap/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/activitysim/cdap/cdap.py b/activitysim/cdap/cdap.py new file mode 100644 index 0000000000..4af73a5b8e --- /dev/null +++ b/activitysim/cdap/cdap.py @@ -0,0 +1,248 @@ +import itertools + +import numpy as np +import pandas as pd + +from ..activitysim import eval_variables + + +def make_interactions(people, hh_id_col, p_type_col): + """ + Make two Pandas DataFrames associating people IDs with two + and three person interactions they have within their households. + + Interactions are strings of numbers representing the makeup + of the interaction, e.g. '12' or '341'. + + Note that for two-person interactions the interaction string is ordered + with the person from the index in the first position of the string + and some other person in the second position. In contrast, + the interaction strings for three-person interactions are not ordered. + The person from the index may be in any position of the string. + + Parameters + ---------- + people : pandas.DataFrame + Table of people data. Must contain at least a household ID + column and a categorization of person type. + hh_id_col : str + Name of the column in `people` that has their household ID. + p_type_col : str + Name of the column in `people` that contains the person type number. + + Returns + ------- + two_interaction : pandas.DataFrame + Interactions between two people. Index will be person IDs taken + from the index of `people`. + The table will have one column called `interaction`. + three_interaction : pandas.DataFrame + Interactions between three people. Index will be person IDs taken + from the index of `people`. + The table will have one column called `interaction`. + + """ + two_fmt = '{}{}'.format + three_fmt = '{}{}{}'.format + two = [] + three = [] + + for hh, df in people.groupby(hh_id_col, sort=False): + # skip households with only one person + if len(df) == 1: + continue + + ptypes = df[p_type_col] + + for pA, pB in itertools.permutations(df.index, 2): + two.append((pA, two_fmt(*ptypes[[pA, pB]]))) + + # now skip households with two people + if len(df) == 2: + continue + + for idx in itertools.combinations(df.index, 3): + combo = three_fmt(*ptypes[list(idx)]) + three.extend((p, combo) for p in idx) + + if two: + two_idx, two_val = zip(*two) + else: + two_idx, two_val = [], [] + + if three: + three_idx, three_val = zip(*three) + else: + three_idx, three_val = [], [] + + return ( + pd.DataFrame({'interaction': two_val}, index=two_idx), + pd.DataFrame({'interaction': three_val}, index=three_idx)) + + +def individual_utilities( + people, hh_id_col, p_type_col, one_spec, two_spec, three_spec): + """ + Calculate CDAP utilities for all individuals. + + Parameters + ---------- + people : pandas.DataFrame + DataFrame of individual people data. + hh_id_col : str + Name of the column in `people` that has their household ID. + p_type_col : str + Name of the column in `people` that contains the person type number. + one_spec : pandas.DataFrame + two_spec : pandas.DataFrame + three_spec : pandas.DataFrame + + Returns + ------- + utilities : pandas.DataFrame + Will have index of `people` and columns for each of the alternatives. + + """ + # calculate single person utilities + # evaluate variables from one_spec expressions + # multiply by one_spec alternative values + one_vars = eval_variables(one_spec.index, people) + one_utils = one_vars.dot(one_spec) + + # make two- and three-person interactions + two_int, three_int = make_interactions(people, hh_id_col, p_type_col) + + # calculate two-interaction utilities + # evaluate variables from two_spec expressions + # multiply by two_spec alternative values + # groupby person and sum + two_vars = eval_variables(two_spec.index, two_int) + two_utils = two_vars.dot(two_spec).groupby(level=0).sum() + + # calculate three-interaction utilities + # evaluate variables from three_spec expressions + # multiply by three_spec alternative values + # groupby person and sum + three_vars = eval_variables(three_spec.index, three_int) + three_utils = three_vars.dot(three_spec).groupby(level=0).sum() + + # add one-, two-, and three-person utilities + utils = one_utils.add( + two_utils, fill_value=0).add(three_utils, fill_value=0) + + return utils + + +def initial_household_utilities(utilities, people, hh_id_col): + """ + Create initial household utilities by grouping and summing utilities + from individual household members. + + Parameters + ---------- + utilities : pandas.DataFrame + Should have the index of `people` and columns for each alternative. + people : pandas.DataFrame + DataFrame of individual people data. + hh_id_col : str + Name of the column in `people` that has their household ID. + + Returns + ------- + hh_util : dict of pandas.Series + Keys will be household IDs and values will be Series + mapping alternative choices to their utility. + + """ + hh_util = {} + + alts = utilities.columns + + for hh_id, df in people.groupby(hh_id_col, sort=False): + utils = utilities.loc[df.index] + hh = [] + + for combo in itertools.product(alts, repeat=len(df)): + hh.append( + (combo, utils.lookup(df.index, combo).sum())) + + idx, u = zip(*hh) + hh_util[hh_id] = pd.Series(u, index=idx) + + return hh_util + + +def apply_final_rules(hh_util, people, hh_id_col, final_rules): + """ + Final rules can be used to set the utility values for certain + household alternatives. Often they are set to zero to reflect + the unavailability of certain alternatives to certain types of people. + + This modifies the `hh_util` data inplace. + + Parameters + ---------- + hh_util : dict of pandas.Series + Keys will be household IDs and values will be Series + mapping alternative choices to their utility. + people : pandas.DataFrame + DataFrame of individual people data. + hh_id_col : str + Name of the column in `people` that has their household ID. + final_rules : pandas.DataFrame + This table must have an index of expressions that can be used + to filter the `people` table. It must have two columns: + the first must have the name of the alternative to which the rule + applies, and the second must have the value of the utility for that + alternative. The names of the columns is not important, but + the order is. + + """ + rule_mask = eval_variables(final_rules.index, people) + + for hh_id, df in people.groupby(hh_id_col, sort=False): + mask = rule_mask.loc[df.index] + utils = hh_util[hh_id] + + for exp, row in final_rules.iterrows(): + m = mask[exp].as_matrix() + + # this crazy business combines three things to figure out + # which household alternatives need to be modified by this rule. + # the three things are: + # - the mask of people for whom the rule expression is true (m) + # - the individual alternative to which the rule applies + # (row.iloc[0]) + # - the alternative combinations for the household (combo) + app = [ + ((np.array([row.iloc[0]] * len(utils.index[0])) == combo) & m + ).any() + for combo in utils.index] + + utils[app] = row.iloc[1] + + +def apply_all_people(hh_util, all_people): + """ + Apply utility adjustments to household alternatives. + + This modifies the `hh_util` data inplace. + + Parameters + ---------- + hh_util : dict of pandas.Series + Keys will be household IDs and values will be Series + mapping alternative choices to their utility. + all_people : pandas.DataFrame + Adjustments to household alternatives, with alternatives in the + index and the adjustment values in the first column. + Index should be household alternatives in the form of tuples + containing individual alternatives, e.g. + ('Mandatory', 'Mandatory', 'Mandatory'), where 'Mandatory' is + one of the alternatives available to individual household members. + Note that these may also be expressed as Python code to save space, + so the previous could also be written as ('Mandatory',) * 3. + + """ + # evaluate all the expressions in the all_people index + all_people.index = [eval(x) for x in all_people.index] diff --git a/activitysim/cdap/tests/__init__.py b/activitysim/cdap/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/activitysim/cdap/tests/data/cdap_1_person.csv b/activitysim/cdap/tests/data/cdap_1_person.csv new file mode 100644 index 0000000000..befb8ffa4a --- /dev/null +++ b/activitysim/cdap/tests/data/cdap_1_person.csv @@ -0,0 +1,24 @@ +Description,Expression,Mandatory,NonMandatory,Home +Age filter 1,age < 30,1,0,0 +Age filter 2,age >= 30,0,1,0 +Type 1 and low age,(ptype == 1) & (age < 25),1,0,0 +Type 2 and high age,(ptype == 2) & (age >= 35),0,0,1 +# The rest of these are corrections so results come out the way I want +Person 2 -> H,age == 21,-1,0,1 +Person 5 -> N,age == 24,-1,0,0 +Person 6 -> M,age == 25,0,-1,0 +Person 7 -> M,age == 26,0,-2,-1 +Person 8 -> N,age == 27,-1,0,-1 +Person 9 -> H,age == 28,-1,-2,0 +Person 10 -> M,age == 29,0,0,-2 +Person 11 -> H,age == 30,0,-1,0 +Person 12 -> H,age == 31,-1,-1,0 +Person 13 -> M,age == 32,0,-1,-3 +Person 14 -> M,age == 33,1,-3,-4 +Person 15 -> N,age == 34,-1,0,-2 +Person 16 -> N,age == 35,-1,0,-3 +Person 17 -> H,age == 36,-2,-1,0 +Person 18 -> H,age == 37,0,-2,0 +# This 50 will get zeroed out later by the forbidden alternatives rules +Person 19 -> H,age == 38,50,-4,0 +Person 20 -> M,age == 39,0,-1,-4 diff --git a/activitysim/cdap/tests/data/cdap_2_person.csv b/activitysim/cdap/tests/data/cdap_2_person.csv new file mode 100644 index 0000000000..9fdda047f9 --- /dev/null +++ b/activitysim/cdap/tests/data/cdap_2_person.csv @@ -0,0 +1,8 @@ +Description,Expression,Mandatory,NonMandatory,Home +Two type 1,interaction == '11',1,0,0 +Two type 2,interaction == '22',0,1,0 +Two type 3,interaction == '33',0,0,1 +One and two,interaction == '12',1,0,0 +Two and one,interaction == '21',0,1,0 +One + three,"interaction in ['13', '31']",0,0,1 +Two + three,"interaction in ['23', '32']",0,1,0 diff --git a/activitysim/cdap/tests/data/cdap_3_person.csv b/activitysim/cdap/tests/data/cdap_3_person.csv new file mode 100644 index 0000000000..eb7e1794d4 --- /dev/null +++ b/activitysim/cdap/tests/data/cdap_3_person.csv @@ -0,0 +1,11 @@ +Description,Expression,Mandatory,NonMandatory,Home +All one,interaction == '111',1,0,0 +All two,interaction == '222',0,1,0 +All three,interaction == '333',0,0,1 +One + one + two,"interaction in ['112', '121', '211']",0,0,1 +One + one + three,"interaction in ['113', '131', '311']",0,0,1 +One + two + two,"interaction in ['122', '212', '221']",1,0,0 +One + two + three,"interaction in ['123', '132', '213', '231', '312', '321']",0,0,1 +One + three + three,"interaction in ['133', '313', '331']",0,1,0 +Two + two + three,"interaction in ['223', '232', '322']",0,0,1 +Two + three + three,"interaction in ['233', '323', '332']",1,0,0 diff --git a/activitysim/cdap/tests/data/cdap_all_people.csv b/activitysim/cdap/tests/data/cdap_all_people.csv new file mode 100644 index 0000000000..7d838aea5e --- /dev/null +++ b/activitysim/cdap/tests/data/cdap_all_people.csv @@ -0,0 +1,7 @@ +Description,Alternative,Value +Three Person All M,"('Mandatory',) * 3",0 +Three Person All N,"('NonMandatory',) * 3",0 +Three Person All H,"('Home',) * 3",0 +Four Person All M,"('Mandatory',) * 4",0 +Four Person All N,"('NonMandatory',) * 4",0 +Four Person All H,"('Home',) * 4",0 diff --git a/activitysim/cdap/tests/data/cdap_final_rules.csv b/activitysim/cdap/tests/data/cdap_final_rules.csv new file mode 100644 index 0000000000..f33694a182 --- /dev/null +++ b/activitysim/cdap/tests/data/cdap_final_rules.csv @@ -0,0 +1,2 @@ +Description,Expression,Alternative,Value +M not allowed for Age 38 and Income 1900,(age == 38) & (income == 1900),Mandatory,0 diff --git a/activitysim/cdap/tests/data/people.csv b/activitysim/cdap/tests/data/people.csv new file mode 100644 index 0000000000..1bb990eb4a --- /dev/null +++ b/activitysim/cdap/tests/data/people.csv @@ -0,0 +1,21 @@ +id,household,ptype,age,income +1,1,1,20,100 +2,2,3,21,200 +3,3,1,22,300 +4,3,1,23,400 +5,4,3,24,500 +6,4,2,25,600 +7,5,3,26,700 +8,5,2,27,800 +9,5,2,28,900 +10,6,1,29,1000 +11,6,3,30,1100 +12,6,1,31,1200 +13,7,1,32,1300 +14,7,3,33,1400 +15,7,2,34,1500 +16,7,2,35,1600 +17,8,1,36,1700 +18,8,3,37,1800 +19,8,2,38,1900 +20,8,1,39,2000 diff --git a/activitysim/cdap/tests/test_cdap.py b/activitysim/cdap/tests/test_cdap.py new file mode 100644 index 0000000000..65ccf569f7 --- /dev/null +++ b/activitysim/cdap/tests/test_cdap.py @@ -0,0 +1,300 @@ +import os.path +from itertools import product + +import pandas as pd +import pandas.util.testing as pdt +import pytest + +from .. import cdap +from ...activitysim import read_model_spec + + +@pytest.fixture(scope='module') +def people(): + return pd.read_csv( + os.path.join(os.path.dirname(__file__), 'data', 'people.csv'), + index_col='id') + + +@pytest.fixture(scope='module') +def one_spec(): + return read_model_spec( + os.path.join( + os.path.dirname(__file__), 'data', 'cdap_1_person.csv')) + + +@pytest.fixture(scope='module') +def two_spec(): + return read_model_spec( + os.path.join( + os.path.dirname(__file__), 'data', 'cdap_2_person.csv')) + + +@pytest.fixture(scope='module') +def three_spec(): + return read_model_spec( + os.path.join( + os.path.dirname(__file__), 'data', 'cdap_3_person.csv')) + + +@pytest.fixture(scope='module') +def final_rules(): + return read_model_spec( + os.path.join( + os.path.dirname(__file__), 'data', 'cdap_final_rules.csv')) + + +@pytest.fixture +def all_people(): + return read_model_spec( + os.path.join( + os.path.dirname(__file__), 'data', 'cdap_all_people.csv'), + expression_name='Alternative') + + +@pytest.fixture(scope='module') +def hh_id_col(): + return 'household' + + +@pytest.fixture(scope='module') +def p_type_col(): + return 'ptype' + + +@pytest.fixture(scope='module') +def individual_utils( + people, hh_id_col, p_type_col, one_spec, two_spec, three_spec): + return cdap.individual_utilities( + people, hh_id_col, p_type_col, one_spec, two_spec, three_spec) + + +@pytest.fixture +def hh_utils(individual_utils, people, hh_id_col): + hh_utils = cdap.initial_household_utilities( + individual_utils, people, hh_id_col) + return hh_utils + + +def test_make_interactions(people, hh_id_col, p_type_col): + expected_two = pd.DataFrame( + {'interaction': [ + '11', # household 3; person 3 + '11', # household 3; person 4 + '32', # household 4; person 5 + '23', # household 4; person 6 + '32', '32', # household 5; person 7 + '23', '22', # household 5; person 8 + '23', '22', # household 5; person 9 + '13', '11', # household 6; person 10 + '31', '31', # household 6; person 11 + '11', '13', # household 6; person 12 + '13', '12', '12', # household 7; person 13 + '31', '32', '32', # household 7; person 14 + '21', '23', '22', # household 7; person 15 + '21', '23', '22', # household 7; person 16 + '13', '12', '11', # household 8; person 17 + '31', '32', '31', # household 8; person 18 + '21', '23', '21', # household 8; person 19 + '11', '13', '12' # household 8; person 20 + ]}, + index=[ + 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, + 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, + 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20 + ]) + + expected_three = pd.DataFrame( + {'interaction': [ + '322', '322', '322', # household 5; people 7, 8, 9 + '131', '131', '131', # household 6; people 10, 11, 12 + '132', '132', '132', # household 7; people 13, 14, 15 + '132', '132', '132', # household 7; people 13, 14, 16 + '122', '122', '122', # household 7; people 13, 15, 16 + '322', '322', '322', # household 7; people 14, 15, 16 + '132', '132', '132', # household 8; people 17, 18, 19 + '131', '131', '131', # household 8; people 17, 18, 20 + '121', '121', '121', # household 8; people 17, 19, 20 + '321', '321', '321' # household 8; people 18, 19, 20 + ]}, + index=[ + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 13, 14, 16, 13, 15, 16, 14, 15, 16, + 17, 18, 19, 17, 18, 20, 17, 19, 20, 18, 19, 20 + ]) + + two, three = cdap.make_interactions(people, hh_id_col, p_type_col) + + pdt.assert_frame_equal(two, expected_two) + pdt.assert_frame_equal(three, expected_three) + + +def test_make_interactions_no_interactions(people, hh_id_col, p_type_col): + people = people.loc[[1, 2, 3]] + + two, three = cdap.make_interactions(people, hh_id_col, p_type_col) + + pdt.assert_frame_equal(two, pd.DataFrame(columns=['interaction'])) + pdt.assert_frame_equal(three, pd.DataFrame(columns=['interaction'])) + + +def test_make_interactions_only_twos(people, hh_id_col, p_type_col): + people = people.loc[[1, 2, 3, 4, 5, 6]] + + expected_two = pd.DataFrame( + {'interaction': [ + '11', # household 3; person 3 + '11', # household 3; person 4 + '32', # household 4; person 5 + '23', # household 4; person 6 + ]}, + index=[3, 4, 5, 6] + ) + + two, three = cdap.make_interactions(people, hh_id_col, p_type_col) + + pdt.assert_frame_equal(two, expected_two) + pdt.assert_frame_equal(three, pd.DataFrame(columns=['interaction'])) + + +def test_individual_utilities(people, one_spec, individual_utils): + expected = pd.DataFrame([ + [2, 0, 0], # person 1 + [0, 0, 1], # person 2 + [3, 0, 0], # person 3 + [3, 0, 0], # person 4 + [0, 1, 0], # person 5 + [1, 0, 0], # person 6 + [1, 0, 0], # person 7 + [0, 2, 0], # person 8 + [0, 0, 1], # person 9 + [2, 0, 0], # person 10 + [0, 0, 3], # person 11 + [0, 0, 2], # person 12 + [3, 0, 0], # person 13 + [1, 0, 0], # person 14 + [0, 4, 0], # person 15 + [0, 4, 0], # person 16 + [0, 0, 4], # person 17 + [0, 0, 5], # person 18 + [50, 0, 4], # person 19 + [2, 0, 0] # person 20 + ], index=people.index, columns=one_spec.columns) + + pdt.assert_frame_equal( + individual_utils, expected, check_dtype=False, check_names=False) + + +def test_initial_household_utilities(hh_utils): + alts = ['Mandatory', 'NonMandatory', 'Home'] + one_alts = list(product(alts, repeat=1)) + two_alts = list(product(alts, repeat=2)) + three_alts = list(product(alts, repeat=3)) + four_alts = list(product(alts, repeat=4)) + + expected = { + 1: pd.Series([2, 0, 0], index=one_alts), + 2: pd.Series([0, 0, 1], index=one_alts), + 3: pd.Series([6, 3, 3, 3, 0, 0, 3, 0, 0], index=two_alts), + 4: pd.Series([1, 0, 0, 2, 1, 1, 1, 0, 0], index=two_alts), + 5: pd.Series([ + 1, 1, 2, 3, 3, 4, 1, 1, 2, + 0, 0, 1, 2, 2, 3, 0, 0, 1, + 0, 0, 1, 2, 2, 3, 0, 0, 1, + ], index=three_alts), + 6: pd.Series([ + 2, 2, 4, 2, 2, 4, 5, 5, 7, + 0, 0, 2, 0, 0, 2, 3, 3, 5, + 0, 0, 2, 0, 0, 2, 3, 3, 5, + ], index=three_alts), + 7: pd.Series([ + 4, 8, 4, 8, 12, 8, 4, 8, 4, + 3, 7, 3, 7, 11, 7, 3, 7, 3, + 3, 7, 3, 7, 11, 7, 3, 7, 3, + 1, 5, 1, 5, 9, 5, 1, 5, 1, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 1, 5, 1, 5, 9, 5, 1, 5, 1, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 0, 4, 0, 4, 8, 4, 0, 4, 0 + ], index=four_alts), + 8: pd.Series([ + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 57, 55, 55, 7, 5, 5, 11, 9, 9, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 57, 55, 55, 7, 5, 5, 11, 9, 9, + 56, 54, 54, 6, 4, 4, 10, 8, 8, + 56, 54, 54, 6, 4, 4, 10, 8, 8, + 61, 59, 59, 11, 9, 9, 15, 13, 13 + ], index=four_alts) + } + + assert list(hh_utils.keys()) == list(expected.keys()) + for k in expected: + pdt.assert_series_equal(hh_utils[k], expected[k], check_dtype=False) + + +def test_apply_final_rules(hh_utils, final_rules, people, hh_id_col): + expected = hh_utils.copy() + expected[8] = pd.Series([ + 0, 0, 0, 2, 0, 0, 6, 4, 4, + 0, 0, 0, 2, 0, 0, 6, 4, 4, + 0, 0, 0, 7, 5, 5, 11, 9, 9, + 0, 0, 0, 2, 0, 0, 6, 4, 4, + 0, 0, 0, 2, 0, 0, 6, 4, 4, + 0, 0, 0, 7, 5, 5, 11, 9, 9, + 0, 0, 0, 6, 4, 4, 10, 8, 8, + 0, 0, 0, 6, 4, 4, 10, 8, 8, + 0, 0, 0, 11, 9, 9, 15, 13, 13 + ], index=expected[7].index) + + cdap.apply_final_rules(hh_utils, people, hh_id_col, final_rules) + + for k in expected: + pdt.assert_series_equal(hh_utils[k], expected[k], check_dtype=False) + + +def test_apply_all_people(hh_utils, all_people): + all_people.at["('Mandatory',) * 3", 'Value'] = 300 + all_people.at["('Home',) * 4", 'Value'] = 500 + + expected = hh_utils.copy() + expected[5] = pd.Series([ + 301, 1, 2, 3, 3, 4, 1, 1, 2, + 0, 0, 1, 2, 2, 3, 0, 0, 1, + 0, 0, 1, 2, 2, 3, 0, 0, 1, + ], index=hh_utils[5].index) + expected[6] = pd.Series([ + 302, 2, 4, 2, 2, 4, 5, 5, 7, + 0, 0, 2, 0, 0, 2, 3, 3, 5, + 0, 0, 2, 0, 0, 2, 3, 3, 5, + ], index=hh_utils[6].index) + expected[7] = pd.Series([ + 4, 8, 4, 8, 12, 8, 4, 8, 4, + 3, 7, 3, 7, 11, 7, 3, 7, 3, + 3, 7, 3, 7, 11, 7, 3, 7, 3, + 1, 5, 1, 5, 9, 5, 1, 5, 1, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 1, 5, 1, 5, 9, 5, 1, 5, 1, + 0, 4, 0, 4, 8, 4, 0, 4, 0, + 0, 4, 0, 4, 8, 4, 0, 4, 500 + ], index=hh_utils[7].index) + expected[8] = pd.Series([ + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 57, 55, 55, 7, 5, 5, 11, 9, 9, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 52, 50, 50, 2, 0, 0, 6, 4, 4, + 57, 55, 55, 7, 5, 5, 11, 9, 9, + 56, 54, 54, 6, 4, 4, 10, 8, 8, + 56, 54, 54, 6, 4, 4, 10, 8, 8, + 61, 59, 59, 11, 9, 9, 15, 13, 513 + ], index=hh_utils[8].index) + + cdap.apply_all_people(hh_utils, all_people) + + for k in expected: + pdt.assert_series_equal(hh_utils[k], expected[k], check_dtype=False) diff --git a/activitysim/defaults/README.md b/activitysim/defaults/README.md new file mode 100644 index 0000000000..1f26af58fb --- /dev/null +++ b/activitysim/defaults/README.md @@ -0,0 +1,4 @@ +Definition of terms: + +* CDAP: coordinated daily activity pattern +* TDD: tour departure and duration \ No newline at end of file diff --git a/activitysim/defaults/__init__.py b/activitysim/defaults/__init__.py index fd8a0284a5..991ff35408 100644 --- a/activitysim/defaults/__init__.py +++ b/activitysim/defaults/__init__.py @@ -1,3 +1,7 @@ # ActivitySim # Copyright (C) 2014-2015 Synthicity, LLC # See full license in LICENSE.txt. + +import misc +import tables +import models diff --git a/activitysim/defaults/datasources.py b/activitysim/defaults/datasources.py deleted file mode 100644 index 50f0bd245f..0000000000 --- a/activitysim/defaults/datasources.py +++ /dev/null @@ -1,87 +0,0 @@ -# ActivitySim -# Copyright (C) 2014-2015 Synthicity, LLC -# See full license in LICENSE.txt. - -import numpy as np -import pandas as pd -import os -import uuid -import yaml -from urbansim.utils import misc -import urbansim.sim.simulation as sim -from .. import activitysim as asim - -import warnings - -warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning) -pd.options.mode.chained_assignment = None - - -@sim.injectable('settings', cache=True) -def settings(): - with open(os.path.join(misc.configs_dir(), "settings.yaml")) as f: - settings = yaml.load(f) - # monkey patch on the settings object since it's pretty global - # but will also be available as injectable - sim.settings = settings - return settings - - -@sim.injectable('run_number') -def run_number(): - return misc.get_run_number() - - -@sim.injectable('uuid', cache=True) -def uuid_hex(): - return uuid.uuid4().hex - - -@sim.injectable('store', cache=True) -def hdfstore(settings): - return pd.HDFStore( - os.path.join(misc.data_dir(), settings["store"]), - mode='r') - - -@sim.injectable("scenario") -def scenario(settings): - return settings["scenario"] - - -@sim.table(cache=True) -def land_use(store): - return store["land_use/taz_data"] - - -@sim.table(cache=True) -def accessibility(store): - df = store["skims/accessibility"] - df.columns = [c.upper() for c in df.columns] - return df - - -@sim.table(cache=True) -def households(store, settings): - - if "households_sample_size" in settings: - return asim.random_rows(store["households"], - settings["households_sample_size"]) - - return store["households"] - - -@sim.table(cache=True) -def persons(store, settings, households): - df = store["persons"] - - if "households_sample_size" in settings: - # keep all persons in the sampled households - df = df[df.household_id.isin(households.index)] - - return df - - -sim.broadcast('households', 'persons', cast_index=True, onto_on='household_id') -sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ') -sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ') diff --git a/activitysim/defaults/misc.py b/activitysim/defaults/misc.py new file mode 100644 index 0000000000..21825023cc --- /dev/null +++ b/activitysim/defaults/misc.py @@ -0,0 +1,69 @@ +import urbansim.sim.simulation as sim +import warnings +import os +import yaml +import pandas as pd +import numpy as np + + +warnings.filterwarnings('ignore', category=pd.io.pytables.PerformanceWarning) +pd.options.mode.chained_assignment = None + + +@sim.injectable() +def configs_dir(): + return '.' + + +@sim.injectable() +def data_dir(): + return '.' + + +@sim.injectable(cache=True) +def settings(configs_dir): + with open(os.path.join(configs_dir, "configs", "settings.yaml")) as f: + return yaml.load(f) + + +@sim.injectable(cache=True) +def store(data_dir, settings): + return pd.HDFStore(os.path.join(data_dir, "data", settings["store"]), + mode='r') + + +# these are the alternatives for the workplace choice, among other things +@sim.table() +def zones(): + # I grant this is a weird idiom but it helps to name the index + return pd.DataFrame({"TAZ": np.arange(1454)+1}).set_index("TAZ") + + +# this is a common merge so might as well define it once here and use it +@sim.table() +def households_merged(households, land_use, accessibility): + return sim.merge_tables(households.name, tables=[households, + land_use, + accessibility]) + + +# another common merge for persons +@sim.table() +def persons_merged(persons, households, land_use, accessibility): + return sim.merge_tables(persons.name, tables=[persons, + households, + land_use, + accessibility]) + + +@sim.table() +def mandatory_tours_merged(mandatory_tours, persons_merged): + return sim.merge_tables(mandatory_tours.name, + [mandatory_tours, persons_merged]) + + +@sim.table() +def non_mandatory_tours_merged(non_mandatory_tours, persons_merged): + tours = non_mandatory_tours + return sim.merge_tables(tours.name, tables=[tours, + persons_merged]) diff --git a/activitysim/defaults/models/__init__.py b/activitysim/defaults/models/__init__.py new file mode 100644 index 0000000000..aa483f0674 --- /dev/null +++ b/activitysim/defaults/models/__init__.py @@ -0,0 +1,11 @@ +# ActivitySim +# Copyright (C) 2014-2015 Synthicity, LLC +# See full license in LICENSE.txt. + +import auto_ownership +import destination +import mandatory_tour_frequency +import non_mandatory_tour_frequency +import mandatory_scheduling +import non_mandatory_scheduling +import workplace_location diff --git a/activitysim/defaults/models/auto_ownership.py b/activitysim/defaults/models/auto_ownership.py new file mode 100644 index 0000000000..3fe40e4f48 --- /dev/null +++ b/activitysim/defaults/models/auto_ownership.py @@ -0,0 +1,42 @@ +import os +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim + +""" +Auto ownership is a standard model which predicts how many cars a household +with given characteristics owns +""" + +# this is the max number of cars allowable in the auto ownership model +MAX_NUM_CARS = 5 + + +@sim.table() +def auto_alts(): + # alts can't be integers directly as they're used in expressions - they + # won't be evaluated correctly by DataFrame.eval unless they're strings + return asim.identity_matrix(["cars%d" % i for i in range(MAX_NUM_CARS)]) + + +@sim.injectable() +def auto_ownership_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', "auto_ownership.csv") + return asim.read_model_spec(f) + + +@sim.model() +def auto_ownership_simulate(households_merged, + auto_alts, + auto_ownership_spec): + + choices, _ = asim.simple_simulate(households_merged.to_frame(), + auto_alts.to_frame(), + auto_ownership_spec, + mult_by_alt_col=True) + + # map these back to integers - this is the actual number of cars chosen + car_map = {"cars%d" % i: i for i in range(MAX_NUM_CARS)} + choices = choices.map(car_map) + + print "Choices:\n", choices.value_counts() + sim.add_column("households", "auto_ownership", choices) diff --git a/activitysim/defaults/models/destination.py b/activitysim/defaults/models/destination.py new file mode 100644 index 0000000000..80363545db --- /dev/null +++ b/activitysim/defaults/models/destination.py @@ -0,0 +1,74 @@ +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim +import os +import pandas as pd + +""" +Given the tour generation from the above, each tour needs to have a +destination, so in this case tours are the choosers (with the associated +person that's making the tour) +""" + + +@sim.table() +def destination_choice_size_terms(configs_dir): + f = os.path.join(configs_dir, 'configs', + 'destination_choice_size_terms.csv') + return pd.read_csv(f) + + +@sim.table() +def destination_choice_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', + 'destination_choice_alternatives_sample.csv') + # FIXME not using all the variables yet + return asim.read_model_spec(f, stack=False).head(5) + + +@sim.model() +def destination_choice(non_mandatory_tours_merged, + zones, + distance_skim, + destination_choice_spec): + + # choosers are tours - in a sense tours are choosing their destination + choosers = non_mandatory_tours_merged.to_frame() + + # FIXME these models don't have size terms at the moment + + # FIXME these models don't use stratified sampling - we're just making + # FIXME the choice with the sampling model + + # all these tours are home based by definition so we use distance to the + # home as the relevant distance here + skims = { + "distance": distance_skim + } + + choices_list = [] + # segment by trip type and pick the right spec for each person type + for name, segment in choosers.groupby('tour_type'): + + # FIXME - there are two options here escort with kids and without + if name == "escort": + continue + + print "Running segment '%s' of size %d" % (name, len(segment)) + + choices, _ = \ + asim.simple_simulate(segment, + zones.to_frame(), + destination_choice_spec[name], + skims, + skim_join_name="TAZ", + mult_by_alt_col=False, + sample_size=50) + + choices_list.append(choices) + + choices = pd.concat(choices_list) + + print "Choices:\n", choices.describe() + # every trip now has a destination which is the index from the + # alternatives table - in this case it's the destination taz + sim.add_column("non_mandatory_tours", "destination", choices) diff --git a/activitysim/defaults/models/mandatory_scheduling.py b/activitysim/defaults/models/mandatory_scheduling.py new file mode 100644 index 0000000000..f210bb0e86 --- /dev/null +++ b/activitysim/defaults/models/mandatory_scheduling.py @@ -0,0 +1,54 @@ +import os +import pandas as pd +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim +from non_mandatory_scheduling import vectorize_tour_schedules + +""" +This model predicts the departure time and duration of each activity for +mandatory tours +""" + + +@sim.table() +def tdd_alts(configs_dir): + # right now this file just contains the start and end hour + f = os.path.join(configs_dir, "configs", + "tour_departure_and_duration_alternatives.csv") + return pd.read_csv(f) + + +# used to have duration in the actual alternative csv file, +# but this is probably better as a computed column like this +@sim.column("tdd_alts") +def duration(tdd_alts): + return tdd_alts.end - tdd_alts.start + + +@sim.table() +def tdd_mandatory_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', + 'tour_departure_and_duration_mandatory.csv') + return asim.read_model_spec(f, stack=False) + + +@sim.model() +def mandatory_scheduling(mandatory_tours_merged, + tdd_alts, + tdd_mandatory_spec): + + tours = mandatory_tours_merged.to_frame() + + print "Running %d mandatory tour scheduling choices" % len(tours) + + # FIXME we're about halfway down the specfile + spec = tdd_mandatory_spec.to_frame().head(27) + alts = tdd_alts.to_frame() + + # FIXME the "windowing" variables are not currently implemented + + choices = vectorize_tour_schedules(tours, alts, spec) + + print "Choices:\n", choices.describe() + + sim.add_column("mandatory_tours", "mandatory_tdd", choices) diff --git a/activitysim/defaults/models/mandatory_tour_frequency.py b/activitysim/defaults/models/mandatory_tour_frequency.py new file mode 100644 index 0000000000..d1ed913bae --- /dev/null +++ b/activitysim/defaults/models/mandatory_tour_frequency.py @@ -0,0 +1,111 @@ +import os +import pandas as pd +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim + +""" +This model predicts the frequency of making mandatory trips (see the +alternatives above) - these trips include work and school in some combination. +""" + + +@sim.table() +def mandatory_tour_frequency_alts(): + return asim.identity_matrix(["work1", "work2", "school1", "school2", + "work_and_school"]) + + +@sim.injectable() +def mandatory_tour_frequency_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', "mandatory_tour_frequency.csv") + return asim.read_model_spec(f) + + +@sim.model() +def mandatory_tour_frequency(persons_merged, + mandatory_tour_frequency_alts, + mandatory_tour_frequency_spec): + + choosers = persons_merged.to_frame() + # filter based on results of CDAP + choosers = choosers[choosers.cdap_activity == 'M'] + print "%d persons run for mandatory tour model" % len(choosers) + + choices, _ = \ + asim.simple_simulate(choosers, + mandatory_tour_frequency_alts.to_frame(), + mandatory_tour_frequency_spec, + mult_by_alt_col=True) + + print "Choices:\n", choices.value_counts() + sim.add_column("persons", "mandatory_tour_frequency", choices) + + +""" +This reprocesses the choice of index of the mandatory tour frequency +alternatives into an actual dataframe of tours. Ending format is +the same as got non_mandatory_tours except trip types are "work" and "school" +""" + + +# TODO this needs a simple input / output unit test +@sim.table() +def mandatory_tours(persons): + + persons = persons.to_frame(columns=["mandatory_tour_frequency", + "is_worker"]) + persons = persons[~persons.mandatory_tour_frequency.isnull()] + + tours = [] + # this is probably easier to do in non-vectorized fashion like this + for key, row in persons.iterrows(): + + mtour = row.mandatory_tour_frequency + is_worker = row.is_worker + + # this logic came from the CTRAMP model - I copied it as best as I + # could from the previous code - basically we need to know which + # tours are the first tour and which are subsequent, and work / + # school depends on the status of the person (is_worker variable) + + # 1 work trip + if mtour == "work1": + tours += [(key, "work", 1)] + # 2 work trips + elif mtour == "work2": + tours += [(key, "work", 1), (key, "work", 2)] + # 1 school trip + elif mtour == "school1": + tours += [(key, "school", 1)] + # 2 school trips + elif mtour == "school2": + tours += [(key, "school", 1), (key, "school", 2)] + # 1 work and 1 school trip + elif mtour == "work_and_school": + if is_worker: + # is worker, work trip goes first + tours += [(key, "work", 1), (key, "school", 2)] + else: + # is student, work trip goes second + tours += [(key, "school", 1), (key, "work", 2)] + else: + assert 0 + + """ + Pretty basic at this point - trip table looks like this so far + person_id tour_type tour_num + 0 4419 work 1 + 1 4419 school 2 + 4 4650 school 1 + 5 10001 school 1 + 6 10001 work 2 + """ + + return pd.DataFrame(tours, columns=["person_id", "tour_type", "tour_num"]) + + +# broadcast mandatory_tours on to persons using the person_id foreign key +sim.broadcast('persons', 'mandatory_tours', + cast_index=True, onto_on='person_id') +sim.broadcast('persons_merged', 'mandatory_tours', + cast_index=True, onto_on='person_id') diff --git a/activitysim/defaults/models/non_mandatory_scheduling.py b/activitysim/defaults/models/non_mandatory_scheduling.py new file mode 100644 index 0000000000..e0d837f8ad --- /dev/null +++ b/activitysim/defaults/models/non_mandatory_scheduling.py @@ -0,0 +1,70 @@ +import os +import pandas as pd +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim + + +""" +This model predicts the departure time and duration of each activity for +non-mandatory tours +""" + + +@sim.table() +def tdd_non_mandatory_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', + 'tour_departure_and_duration_nonmandatory.csv') + return asim.read_model_spec(f, stack=False) + + +# FIXME - move to activitysim, test, document +def vectorize_tour_schedules(tours, alts, spec): + + max_num_trips = tours.groupby('person_id').size().max() + + # because this is Python, we have to vectorize everything by doing the + # "nth" trip for each person in a for loop (in other words, because each + # trip is dependent on the time windows left by the previous decision) - + # hopefully this will work out ok! + + choices = [] + + for i in range(max_num_trips): + + nth_tours = tours.groupby('person_id').nth(i) + + print "Running %d non-mandatory #%d tour choices" % \ + (len(nth_tours), i+1) + + # FIXME below two lines are placeholders - need a general way to do this + + alts["mode_choice_logsum"] = 0 + nth_tours["end_of_previous_tour"] = -1 + + nth_choices, _ = \ + asim.simple_simulate(nth_tours, alts, spec, mult_by_alt_col=False) + + choices.append(nth_choices) + + # return the concatenated choices + return pd.concat(choices) + + +@sim.model() +def non_mandatory_scheduling(non_mandatory_tours_merged, + tdd_alts, + tdd_non_mandatory_spec): + + tours = non_mandatory_tours_merged.to_frame() + + print "Running %d non-mandatory tour scheduling choices" % len(tours) + + # FIXME we're not even halfway down the specfile + spec = tdd_non_mandatory_spec.Coefficient.head(4) + alts = tdd_alts.to_frame() + + choices = vectorize_tour_schedules(tours, alts, spec) + + print "Choices:\n", choices.describe() + + sim.add_column("non_mandatory_tours", "non_mandatory_tdd", choices) diff --git a/activitysim/defaults/models/non_mandatory_tour_frequency.py b/activitysim/defaults/models/non_mandatory_tour_frequency.py new file mode 100644 index 0000000000..318502ac6a --- /dev/null +++ b/activitysim/defaults/models/non_mandatory_tour_frequency.py @@ -0,0 +1,124 @@ +import os +import pandas as pd +import numpy as np +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim + + +""" +This model predicts the frequency of making non-mandatory trips +(alternatives for this model come from a seaparate csv file which is +configured by the user) - these trips include escort, shopping, othmaint, +othdiscr, eatout, and social trips in various combination. +""" + + +@sim.injectable() +def non_mandatory_tour_frequency_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', "non_mandatory_tour_frequency.csv") + # this is a spec in already stacked format + # it also has multiple segments in different columns in the spec + return asim.read_model_spec(f, stack=False) + + +@sim.table() +def non_mandatory_tour_frequency_alts(configs_dir): + f = os.path.join(configs_dir, "configs", + "non_mandatory_tour_frequency_alternatives.csv") + return pd.read_csv(f) + + +# this a computed variable of the alts used in the model +@sim.column("non_mandatory_tour_frequency_alts") +def tot_tours(non_mandatory_tour_frequency_alts): + # this assumes that the alt dataframe is only counts of trip types + return non_mandatory_tour_frequency_alts.local.sum(axis=1) + + +@sim.model() +def non_mandatory_tour_frequency(persons_merged, + non_mandatory_tour_frequency_alts, + non_mandatory_tour_frequency_spec): + + choosers = persons_merged.to_frame() + + # filter based on results of CDAP + choosers = choosers[choosers.cdap_activity.isin(['M', 'N'])] + print "%d persons run for non-mandatory tour model" % len(choosers) + + choices_list = [] + # segment by person type and pick the right spec for each person type + for name, segment in choosers.groupby('ptype_cat'): + + print "Running segment '%s' of size %d" % (name, len(segment)) + + choices, _ = \ + asim.simple_simulate(segment, + non_mandatory_tour_frequency_alts.to_frame(), + # notice that we pick the column for the + # segment for each segment we run + non_mandatory_tour_frequency_spec[name], + mult_by_alt_col=False) + choices_list.append(choices) + + choices = pd.concat(choices_list) + + print "Choices:\n", choices.value_counts() + # this is adding the INDEX of the alternative that is chosen - when + # we use the results of this choice we will need both these indexes AND + # the alternatives themselves + sim.add_column("persons", "non_mandatory_tour_frequency", choices) + + +""" +We have now generated non-mandatory tours, but they are attributes of the +person table - this function creates a "tours" table which +has one row per tour that has been generated (and the person id it is +associated with) +""" + + +# TODO this needs a simple input / output unit test +@sim.table() +def non_mandatory_tours(persons, + non_mandatory_tour_frequency_alts): + + # get the actual alternatives for each person - have to go back to the + # non_mandatory_tour_frequency_alts dataframe to get this - the choice + # above just stored the index values for the chosen alts + tours = non_mandatory_tour_frequency_alts.local.\ + loc[persons.non_mandatory_tour_frequency] + + # assign person ids to the index + tours.index = persons.index[~persons.non_mandatory_tour_frequency.isnull()] + + # reformat with the columns given below + tours = tours.stack().reset_index() + tours.columns = ["person_id", "tour_type", "num_tours"] + + # now do a repeat and a take, so if you have two trips of given type you + # now have two rows, and zero trips yields zero rows + tours = tours.take(np.repeat(tours.index.values, tours.num_tours.values)) + + # make index unique and drop num_tours since we don't need it anymore + tours = tours.reset_index(drop=True).drop("num_tours", axis=1) + + """ + Pretty basic at this point - trip table looks like this so far + person_id tour_type + 0 4419 escort + 1 4419 escort + 2 4419 othmaint + 3 4419 eatout + 4 4419 social + 5 10001 escort + 6 10001 escort + """ + return tours + + +# broadcast trips onto persons using the person_id +sim.broadcast('persons', 'non_mandatory_tours', + cast_index=True, onto_on='person_id') +sim.broadcast('persons_merged', 'non_mandatory_tours', + cast_index=True, onto_on='person_id') diff --git a/activitysim/defaults/models/workplace_location.py b/activitysim/defaults/models/workplace_location.py new file mode 100644 index 0000000000..f5cd0cd71a --- /dev/null +++ b/activitysim/defaults/models/workplace_location.py @@ -0,0 +1,78 @@ +import os +import urbansim.sim.simulation as sim +from activitysim import activitysim as asim +import pandas as pd +import numpy as np + +""" +The workplace location model predicts the zones in which various people will +work. Interestingly there's not really any supply side to this model - we +assume that in a properly calibrated model there are workplaces for the people +to work. +""" + + +@sim.injectable() +def workplace_location_spec(configs_dir): + f = os.path.join(configs_dir, 'configs', "workplace_location.csv") + return asim.read_model_spec(f) + + +# FIXME there's enough here that this needs to be a utility in activitysim +# FIXME core and documented and tested +@sim.table() +def workplace_size_terms(land_use, destination_choice_size_terms): + """ + This method takes the land use data and multiplies various columns of the + land use data by coefficients from the workplace_size_spec table in order + to yield a size term (a linear combination of land use variables) with + specified coefficients for different segments (like low, med, and high + income) + """ + land_use = land_use.to_frame() + + df = destination_choice_size_terms.to_frame().query("purpose == 'work'") + df = df.drop("purpose", axis=1).set_index("segment") + + new_df = {} + for index, row in df.iterrows(): + + missing = row[~row.index.isin(land_use.columns)] + + if len(missing) > 0: + print "WARNING: missing columns in land use\n", missing.index + + row = row[row.index.isin(land_use.columns)] + sparse = land_use[list(row.index)] + new_df["size_"+index] = np.dot(sparse.as_matrix(), row.values) + + new_df = pd.DataFrame(new_df, index=land_use.index) + return new_df + + +# 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(persons_merged, + zones, + workplace_location_spec, + distance_skim, + workplace_size_terms): + + choosers = persons_merged.to_frame() + alternatives = zones.to_frame().join(workplace_size_terms.to_frame()) + + skims = { + "distance": distance_skim + } + + choices, _ = asim.simple_simulate(choosers, + alternatives, + workplace_location_spec, + skims, + skim_join_name="TAZ", + mult_by_alt_col=False, + sample_size=50) + + print "Describe of choices:\n", choices.describe() + sim.add_column("persons", "workplace_taz", choices) diff --git a/activitysim/defaults/tables/__init__.py b/activitysim/defaults/tables/__init__.py new file mode 100644 index 0000000000..3c194aa1c8 --- /dev/null +++ b/activitysim/defaults/tables/__init__.py @@ -0,0 +1,9 @@ +# ActivitySim +# Copyright (C) 2014-2015 Synthicity, LLC +# See full license in LICENSE.txt. + +import households +import persons +import landuse +import skims +import accessibility diff --git a/activitysim/defaults/tables/accessibility.py b/activitysim/defaults/tables/accessibility.py new file mode 100644 index 0000000000..cc3353d793 --- /dev/null +++ b/activitysim/defaults/tables/accessibility.py @@ -0,0 +1,21 @@ +import pandas as pd +import urbansim.sim.simulation as sim + + +@sim.table(cache=True) +def accessibility(store): + df = store["skims/accessibility"] + df.columns = [c.upper() for c in df.columns] + return df + + +@sim.column("accessibility") +def mode_choice_logsums(accessibility): + # TODO a big todo here is to compute actual mode choice logsums from our + # TODO upcoming mode choice model + return pd.Series(0, accessibility.index) + + +# this would be accessibility around the household location - be careful with +# this one as accessibility at some other location can also matter +sim.broadcast('accessibility', 'households', cast_index=True, onto_on='TAZ') diff --git a/activitysim/defaults/tables/households.py b/activitysim/defaults/tables/households.py new file mode 100644 index 0000000000..b4b16482a0 --- /dev/null +++ b/activitysim/defaults/tables/households.py @@ -0,0 +1,231 @@ +import pandas as pd +import numpy as np +import urbansim.sim.simulation as sim +import urbansim.utils.misc as usim_misc +from activitysim import activitysim as asim + + +@sim.table(cache=True) +def households(store, settings): + + if "households_sample_size" in settings: + return asim.random_rows(store["households"], + settings["households_sample_size"]) + + return store["households"] + + +sim.broadcast('households', 'persons', cast_index=True, onto_on='household_id') + + +@sim.column("households") +def income_in_thousands(households): + return households.income / 1000 + + +@sim.column("households") +def income_segment(households): + return pd.cut(households.income_in_thousands, + bins=[-np.inf, 30, 60, 100, np.inf], + labels=[1, 2, 3, 4]) + + +@sim.column("households") +def non_workers(households, persons): + return persons.household_id.value_counts() - households.workers + + +@sim.column("households") +def drivers(households, persons): + # we assume that everyone 16 and older is a potential driver + return persons.local.query("16 <= age").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def num_young_children(households, persons): + return persons.local.query("age <= 4").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def num_children(households, persons): + return persons.local.query("5 <= age <= 15").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def num_adolescents(households, persons): + return persons.local.query("16 <= age <= 17").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def num_college_age(households, persons): + return persons.local.query("18 <= age <= 24").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def num_young_adults(households, persons): + return persons.local.query("25 <= age <= 34").\ + groupby("household_id").size().\ + reindex(households.index).fillna(0) + + +# just a rename / alias +@sim.column("households") +def home_taz(households): + return households.TAZ + + +# map household type ids to strings +@sim.column("households") +def household_type(households, settings): + return households.HHT.map(settings["household_type_map"]) + + +@sim.column("households") +def non_family(households): + return households.household_type.isin(["nonfamily_male_alone", + "nonfamily_male_notalone", + "nonfamily_female_alone", + "nonfamily_female_notalone"]) + + +# can't just invert these unfortunately because there's a null household type +@sim.column("households") +def family(households): + return households.household_type.isin(["family_married", + "family_male", + "family_female"]) + + +@sim.column("households") +def num_under16_not_at_school(persons, households): + return persons.under16_not_at_school.groupby(persons.household_id).size().\ + reindex(households.index).fillna(0) + + +@sim.column("households") +def auto_ownership(households): + # 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(0, households.index) + + +@sim.column('households') +def no_cars(households): + return (households.auto_ownership == 0) + + +@sim.column('households') +def home_is_urban(households, land_use, settings): + s = usim_misc.reindex(land_use.area_type, households.home_taz) + return s < settings['urban_threshold'] + + +@sim.column('households') +def home_is_rural(households, land_use, settings): + s = usim_misc.reindex(land_use.area_type, households.home_taz) + return s > settings['rural_threshold'] + + +@sim.column('households') +def car_sufficiency(households, persons): + return households.auto_ownership - persons.household_id.value_counts() + + +@sim.column('households') +def work_tour_auto_time_savings(households): + # TODO fix this variable from auto ownership model + return pd.Series(0, households.index) + + +# this is an idiom to grab the person of the specified type and check to see if +# there is 1 or more of that kind of person in each household +def presence_of(ptype, persons, households, at_home=False): + if at_home: + # if at_home, they need to be of given type AND at home + s = persons.household_id[(persons.ptype_cat == ptype) & + (persons.cdap_activity == "H")] + else: + s = persons.household_id[persons.ptype_cat == ptype] + + return (s.value_counts() > 0).reindex(households.index).fillna(False) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_non_worker(persons, households): + return presence_of("nonwork", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_retiree(persons, households): + return presence_of("retired", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_preschool_kid(persons, households): + return presence_of("preschool", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_preschool_kid_at_home(persons, households): + return presence_of("preschool", persons, households, at_home=True) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_driving_kid(persons, households): + return presence_of("driving", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_school_kid(persons, households): + return presence_of("school", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_school_kid_at_home(persons, households): + return presence_of("school", persons, households, at_home=True) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_full_time(persons, households): + return presence_of("full", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_part_time(persons, households): + return presence_of("part", persons, households) + + +# FIXME this is in non-mandatory tour generation - and should really be from +# FIXME the perspective of the current chooser - which it's not right now +@sim.column('households') +def has_university(persons, households): + return presence_of("university", persons, households) diff --git a/activitysim/defaults/tables/landuse.py b/activitysim/defaults/tables/landuse.py new file mode 100644 index 0000000000..d0bc974277 --- /dev/null +++ b/activitysim/defaults/tables/landuse.py @@ -0,0 +1,52 @@ +import urbansim.sim.simulation as sim + + +@sim.table(cache=True) +def land_use(store): + return store["land_use/taz_data"] + + +sim.broadcast('land_use', 'households', cast_index=True, onto_on='TAZ') + + +@sim.column("land_use") +def total_households(land_use): + return land_use.local.TOTHH + + +@sim.column("land_use") +def total_employment(land_use): + return land_use.local.TOTEMP + + +@sim.column("land_use") +def total_acres(land_use): + return land_use.local.TOTACRE + + +@sim.column("land_use") +def county_id(land_use): + return land_use.local.COUNTY + + +@sim.column("land_use") +def household_density(land_use): + return land_use.total_households / land_use.total_acres + + +@sim.column("land_use") +def employment_density(land_use): + return land_use.total_employment / land_use.total_acres + + +@sim.column("land_use") +def density_index(land_use): + return (land_use.household_density * land_use.employment_density) / \ + (land_use.household_density + land_use.employment_density) + + +@sim.column("land_use") +def county_name(land_use, settings): + assert "county_map" in settings + inv_map = {v: k for k, v in settings["county_map"].items()} + return land_use.county_id.map(inv_map) diff --git a/activitysim/defaults/tables/persons.py b/activitysim/defaults/tables/persons.py new file mode 100644 index 0000000000..a1223c73ff --- /dev/null +++ b/activitysim/defaults/tables/persons.py @@ -0,0 +1,210 @@ +import pandas as pd +import numpy as np +import urbansim.sim.simulation as sim +import urbansim.utils.misc as usim_misc + + +@sim.table(cache=True) +def persons(store, settings, households): + df = store["persons"] + + if "households_sample_size" in settings: + # keep all persons in the sampled households + df = df[df.household_id.isin(households.index)] + + return df + + +# FIXME - this is my "placeholder" for the CDAP model ;) +@sim.column("persons") +def cdap_activity(persons): + return pd.Series(np.random.randint(3, size=len(persons)), + index=persons.index).map({0: 'M', 1: 'N', 2: 'H'}) + + +# FIXME - these are my "placeholder" for joint trip generation +# number of joint shopping tours +@sim.column("persons") +def num_shop_j(persons): + return pd.Series(0, persons.index) + + +# FIXME - these are my "placeholder" for joint trip generation +# number of joint shopping tours +@sim.column("persons") +def num_main_j(persons): + return pd.Series(0, persons.index) + + +# FIXME - these are my "placeholder" for joint trip generation +# number of joint shopping tours +@sim.column("persons") +def num_eat_j(persons): + return pd.Series(0, persons.index) + + +# FIXME - these are my "placeholder" for joint trip generation +# number of joint shopping tours +@sim.column("persons") +def num_visi_j(persons): + return pd.Series(0, persons.index) + + +# FIXME - these are my "placeholder" for joint trip generation +# number of joint shopping tours +@sim.column("persons") +def num_disc_j(persons): + return pd.Series(0, persons.index) + + +@sim.column("persons") +def num_joint_tours(persons): + return persons.num_shop_j + persons.num_main_j + persons.num_eat_j +\ + persons.num_visi_j + persons.num_disc_j + + +@sim.column("persons") +def male(persons): + return persons.sex == 1 + + +@sim.column("persons") +def female(persons): + return persons.sex == 1 + + +# 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) + + s = persons.mandatory_tour_frequency.map({ + "work1": 1, + "work2": 2, + "school1": 1, + "school2": 2, + "work_and_school": 2 + }) + return s + + +# FIXME now totally sure what this is but it's used in non mandatory tour +# FIXME generation and probably has to do with remaining unscheduled time +@sim.column('persons') +def max_window(persons): + return pd.Series(0, persons.index) + + +# convert employment categories to string descriptors +@sim.column("persons") +def employed_cat(persons, settings): + return persons.pemploy.map(settings["employment_map"]) + + +# convert student categories to string descriptors +@sim.column("persons") +def student_cat(persons, settings): + return persons.pstudent.map(settings["student_map"]) + + +# convert person type categories to string descriptors +@sim.column("persons") +def ptype_cat(persons, settings): + return persons.ptype.map(settings["person_type_map"]) + + +# borrowing these definitions from the original code +@sim.column("persons") +def student_is_employed(persons): + return (persons.ptype_cat.isin(['university', 'driving']) & + persons.employed_cat.isin(['full', 'part'])) + + +@sim.column("persons") +def nonstudent_to_school(persons): + return (persons.ptype_cat.isin(['full', 'part', 'nonwork', 'retired']) & + persons.student_cat.isin(['high', 'college'])) + + +@sim.column("persons") +def under16_not_at_school(persons): + return (persons.ptype_cat.isin(["school", "preschool"]) & + persons.cdap_activity.isin(["N", "H"])) + + +@sim.column("persons") +def is_worker(persons): + return persons.employed_cat.isin(['full', 'part']) + + +@sim.column("persons") +def is_student(persons): + return persons.student_cat.isin(['high', 'college']) + + +@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) + + +@sim.column("persons") +def home_taz(households, persons): + return usim_misc.reindex(households.home_taz, + persons.household_id) + + +@sim.column("persons") +def school_taz(persons): + # FIXME need to fix this after getting school lcm working + return persons.workplace_taz + + +# this use the distance skims to compute the raw distance to work from home +@sim.column("persons") +def distance_to_work(persons, distance_skim): + return pd.Series(distance_skim.get(persons.home_taz, + persons.workplace_taz), + index=persons.index) + + +# same deal but to school +@sim.column("persons") +def distance_to_school(persons, distance_skim): + return pd.Series(distance_skim.get(persons.home_taz, + persons.school_taz), + index=persons.index) + + +# similar but this adds the am peak travel time to the pm peak travel time in +# the opposite direction (by car) +@sim.column("persons") +def roundtrip_auto_time_to_work(persons, sovam_skim, sovpm_skim): + return pd.Series(sovam_skim.get(persons.home_taz, + persons.workplace_taz) + + sovpm_skim.get(persons.workplace_taz, + persons.home_taz), + index=persons.index) + + +# this adds the am peak travel time to the md peak travel time in +# the opposite direction (by car), assuming students leave school earlier +@sim.column("persons") +def roundtrip_auto_time_to_school(persons, sovam_skim, sovmd_skim): + return pd.Series(sovam_skim.get(persons.home_taz, + persons.school_taz) + + sovmd_skim.get(persons.school_taz, + persons.home_taz), + index=persons.index) + + +@sim.column('persons') +def workplace_in_cbd(persons, land_use, settings): + s = usim_misc.reindex(land_use.area_type, persons.workplace_taz) + return s < settings['cbd_threshold'] diff --git a/activitysim/defaults/tables/skims.py b/activitysim/defaults/tables/skims.py new file mode 100644 index 0000000000..f8adfca780 --- /dev/null +++ b/activitysim/defaults/tables/skims.py @@ -0,0 +1,41 @@ +import urbansim.sim.simulation as sim +import openmatrix as omx +from activitysim import skim +import os + +""" +Read in the omx files and create the skim objects +""" + + +@sim.injectable() +def nonmotskm_omx(data_dir): + return omx.openFile(os.path.join(data_dir, 'data', "nonmotskm.omx")) + + +@sim.injectable() +def nonmotskm_matrix(nonmotskm_omx): + return nonmotskm_omx['DIST'] + + +@sim.injectable() +def distance_skim(nonmotskm_matrix): + return skim.Skim(nonmotskm_matrix, offset=-1) + + +@sim.injectable() +def sovam_skim(nonmotskm_matrix): + # FIXME use the right omx file + return skim.Skim(nonmotskm_matrix, offset=-1) + + +@sim.injectable() +def sovmd_skim(nonmotskm_matrix): + # FIXME use the right omx file + return skim.Skim(nonmotskm_matrix, offset=-1) + + +@sim.injectable() +def sovpm_skim(nonmotskm_matrix): + # FIXME use the right omx file + return skim.Skim(nonmotskm_matrix, offset=-1) diff --git a/activitysim/defaults/test/__init__.py b/activitysim/defaults/test/__init__.py new file mode 100644 index 0000000000..fd8a0284a5 --- /dev/null +++ b/activitysim/defaults/test/__init__.py @@ -0,0 +1,3 @@ +# ActivitySim +# Copyright (C) 2014-2015 Synthicity, LLC +# See full license in LICENSE.txt. diff --git a/activitysim/defaults/test/test.h5 b/activitysim/defaults/test/test.h5 new file mode 100644 index 0000000000..ba859a8809 Binary files /dev/null and b/activitysim/defaults/test/test.h5 differ diff --git a/activitysim/defaults/test/test_defaults.py b/activitysim/defaults/test/test_defaults.py new file mode 100644 index 0000000000..73d37b1a62 --- /dev/null +++ b/activitysim/defaults/test/test_defaults.py @@ -0,0 +1,48 @@ +# ActivitySim +# Copyright (C) 2014-2015 Synthicity, LLC +# See full license in LICENSE.txt. + + +import pytest +import os +import pandas as pd +import numpy as np +import urbansim.sim.simulation as sim +from .. import __init__ + + +@pytest.fixture(scope="module") +def store(request): + store = pd.HDFStore( + os.path.join(os.path.dirname(__file__), 'test.h5'), "r") + + def fin(): + store.close() + request.addfinalizer(fin) + + return store + + +def test_mini_run(store): + sim.add_injectable("configs_dir", + os.path.join(os.path.dirname(__file__), '..', '..', + '..', 'example')) + + sim.add_injectable("store", store) + + sim.add_injectable("nonmotskm_matrix", np.ones((1454, 1454))) + + # grab some of the tables + sim.get_table("land_use").to_frame().info() + sim.get_table("households").to_frame().info() + sim.get_table("persons").to_frame().info() + + # run the models in the expected order + sim.run(["workplace_location_simulate"]) + sim.run(["auto_ownership_simulate"]) + sim.run(['mandatory_tour_frequency']) + sim.run(['non_mandatory_tour_frequency']) + sim.get_table("non_mandatory_tours").tour_type.value_counts() + sim.run(["destination_choice"]) + sim.run(["mandatory_scheduling"]) + sim.run(["non_mandatory_scheduling"]) diff --git a/activitysim/defaults/variables.py b/activitysim/defaults/variables.py deleted file mode 100644 index c50a58bba7..0000000000 --- a/activitysim/defaults/variables.py +++ /dev/null @@ -1,86 +0,0 @@ -# ActivitySim -# Copyright (C) 2014-2015 Synthicity, LLC -# See full license in LICENSE.txt. - -import pandas as pd -import numpy as np -import urbansim.sim.simulation as sim -from activitysim.defaults import datasources - - -@sim.column("households") -def income_in_thousands(households): - return households.income / 1000 - - -@sim.column("households") -def income_segment(households): - return pd.cut(households.income_in_thousands, - bins=[-np.inf, 30, 60, 100, np.inf], - labels=[1, 2, 3, 4]) - - -@sim.column("households") -def drivers(households, persons): - # we assume that everyone 16 and older is a potential driver - return persons.local.query("16 <= age").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("households") -def num_young_children(households, persons): - return persons.local.query("age <= 4").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("households") -def num_children(households, persons): - return persons.local.query("5 <= age <= 15").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("households") -def num_adolescents(households, persons): - return persons.local.query("16 <= age <= 17").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("households") -def num_college_age(households, persons): - return persons.local.query("18 <= age <= 24").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("households") -def num_young_adults(households, persons): - return persons.local.query("25 <= age <= 34").\ - groupby("household_id").size().\ - reindex(households.index).fillna(0) - - -@sim.column("land_use") -def household_density(land_use): - return land_use.total_households / land_use.total_acres - - -@sim.column("land_use") -def employment_density(land_use): - return land_use.total_employment / land_use.total_acres - - -@sim.column("land_use") -def density_index(land_use): - return (land_use.household_density * land_use.employment_density) / \ - (land_use.household_density + land_use.employment_density) - - -@sim.column("land_use") -def county_name(land_use, settings): - assert "county_map" in settings - inv_map = {v: k for k, v in settings["county_map"].items()} - return land_use.county_id.map(inv_map) diff --git a/activitysim/tests/data/data.csv b/activitysim/tests/data/data.csv new file mode 100644 index 0000000000..b3360c6e81 --- /dev/null +++ b/activitysim/tests/data/data.csv @@ -0,0 +1,4 @@ +thing1,thing2 +1,4 +2,4 +2,6 diff --git a/activitysim/tests/data/sample_spec.csv b/activitysim/tests/data/sample_spec.csv new file mode 100644 index 0000000000..3ec3495f90 --- /dev/null +++ b/activitysim/tests/data/sample_spec.csv @@ -0,0 +1,4 @@ +description,expression,alt0,alt1 +first row,thing1 == 1,11,111 +second row,thing1 == 2,22,222 +third row,@df.thing2.clip(upper=5),33,333 diff --git a/activitysim/tests/test_activitysim.py b/activitysim/tests/test_activitysim.py new file mode 100644 index 0000000000..17bf941742 --- /dev/null +++ b/activitysim/tests/test_activitysim.py @@ -0,0 +1,65 @@ +import os.path + +import numpy.testing as npt +import pandas as pd +import pandas.util.testing as pdt +import pytest + +from .. import activitysim as asim + + +@pytest.fixture(scope='module') +def spec_name(): + return os.path.join(os.path.dirname(__file__), 'data', 'sample_spec.csv') + + +@pytest.fixture(scope='module') +def data_name(): + return os.path.join(os.path.dirname(__file__), 'data', 'data.csv') + + +@pytest.fixture(scope='module') +def spec(spec_name): + return asim.read_model_spec( + spec_name, + description_name='description', expression_name='expression') + + +@pytest.fixture(scope='module') +def data(data_name): + return pd.read_csv(data_name) + + +def test_read_model_spec(spec_name): + spec = asim.read_model_spec( + spec_name, + description_name='description', expression_name='expression') + + assert len(spec) == 3 + assert spec.index.name == 'expression' + assert list(spec.columns) == ['alt0', 'alt1'] + + +def test_identity_matrix(): + names = ['a', 'b', 'c'] + i = asim.identity_matrix(names) + + assert list(i.columns) == names + assert list(i.index) == names + + npt.assert_array_equal( + i.as_matrix(), + [[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + + +def test_eval_variables(spec, data): + result = asim.eval_variables(spec.index, data) + + pdt.assert_frame_equal( + result, + pd.DataFrame([ + [True, False, 4], + [False, True, 4], + [False, True, 5]], + index=data.index, columns=spec.index), + check_names=False) diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000000..faf654620c --- /dev/null +++ b/example/README.md @@ -0,0 +1,78 @@ +#### A few overarching principles + +* A little discussion of "NOT so object oriented" - this is more like a +database - data is in standard tables, NOT in objects... although the +simulation framework is sort of like adding methods to objects + +* The implications of this are that most of the core code is pandas and thus +the quality is controlled by the larger community. We are thankful that its +quality is very high. Specifically, there's not so much code in activitysim +"proper" - activitysim will probably be a set of utilities to do esoteric +things, like CDAP or like tour scheduling. + +* What it takes to add a new model + * define a new model + * define any new data sources necessary + * add any new assumptions in settings.yaml + * co-create the spec and any variables that are too complicated (or + reusable) for the spec + * run in notebook + +* Literally everything is really Python functions that compute something. +Case study of `num_under16_not_at_school` to show the inter-dependencies. + + +#### A few questions about "best practices" + +* What to put into the defaults directory and what to put in the example +/ client-specific stuff? In other words, how much can be shared between +regions? + +* Are we ok with file organization as it exists? Models directory and +tables directory? + +* How much variable computation to put in excel versus Python. For now I've +been putting as much an excel as possible, which allows more "configuration." + +* I've made an effort to not have such "magic numbers" in Python code, but +these definitely occur in the csv configuration. For instance, a variable +for income > 100 thousand has `100` hard-coded in the csv. + +* Want to name or number the person types in the spec files (currently +numbered)? + +* We could possilby use YAML to configure the model runs - is the +model code too much code for a modeler to manage or is this just +right as it makes the model execution transparent to the modeler? +Too much boilerplate or just the right amount? Depends on whether +this can be shared between regions and pretty much stays constant? + +* Big issue: testing for client-specific code? It's harder because outputs are "data +dependent." It's easier to take a small dataset and make sure it always runs, which +is what we do now. At some point we can start actually checking results? +Test against current model system on a model-by-model basis (ouch)? + +* Should I go back and put the Q&A I've had with Dave as issues on +github to save for posterity? Seems like questions as issues is a pretty +good repo for FAQs. + + +#### This is a list of items to double check before using in practice: + +* Make sure the units in things like distance_to_work match the walk thresholds + in the mandatory tour frequency spec. The original divided by 100. This is + true also of round trip auto to work and round trip auto to school. + +* There might be a few variables left off of some of the models. Look for +`head` in reading of the spec files as this is meant to eliminate some of the + rows. Also can look for `#` to comment out variables in the spec. + +* Go back to the 3 school location choices, and run the models for the +appropriate persons. + +* Probably needs code review of the variable definitions. How much of the +variable definitions are shared between regions and how much unique? Age +categories are shared? Income categories are unique? + +* This will be pretty easy to catch, but need to make sure the models run +with Matt's changes to simple simulate that are coming. diff --git a/example/configs/auto_ownership.csv b/example/configs/auto_ownership.csv new file mode 100644 index 0000000000..d09282789d --- /dev/null +++ b/example/configs/auto_ownership.csv @@ -0,0 +1,30 @@ +Description,Expression,cars0,cars1,cars2,cars3,cars4 +2 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.6616 +3 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.208 +4+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807 +Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313 +Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107 +Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596 +Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627 +Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769 +"Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797 +"Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619 +"Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147 +"Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147 +"Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654 +"Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766 +"Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654 +"Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766 +Constants,@1,,1.1865,-1.0846,-3.2502,-5.313 +San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458 +Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372 +Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372 +Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372 +Marin county,county_name == 'Marin',,-0.2434,0,0,0 +"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626 +"Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646 +"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053 +"Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117 +"Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03 +"Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03 +"Auto time savings per worker (over walk or transit, max 120) to work",work_tour_auto_time_savings / (workers+1),,0.4707,0.6142,0.5705,0.7693 \ No newline at end of file diff --git a/example/configs/auto_ownership_coeffs.csv b/example/configs/auto_ownership_coeffs.csv deleted file mode 100644 index 0fe176c110..0000000000 --- a/example/configs/auto_ownership_coeffs.csv +++ /dev/null @@ -1 +0,0 @@ -Description,Expression,cars0,cars1,cars2,cars3,cars4 2 Adults (age 16+),drivers==2,,0,3.0773,3.1962,2.6616 3 Adults (age 16+),drivers==3,,0,3.5401,5.5131,5.208 4+ Adults (age 16+),drivers>3,,2.0107,6.3662,8.5148,9.5807 Persons age 16-17,num_adolescents,,0,-0.881,-1.7313,-1.7313 Persons age 18-24,num_college_age,,-0.4087,-1.0095,-1.0107,-1.0107 Persons age 35-34,num_young_adults,,0,-0.4849,-0.8596,-0.8596 Presence of children age 0-4,num_young_children>0,,0.3669,0.7627,0.7627,0.7627 Presence of children age 5-17,(num_children+num_adolescents)>0,,0.0158,0.2936,0.4769,0.4769 "Number of workers, capped at 3",@df.workers.clip(upper=3),,0,0.2936,0.6389,0.8797 "Piecewise Linear household income, $0-30k","@df.income_in_thousands.clip(0, 30)",,0.0383,0.054,0.0559,0.0619 "Piecewise Linear household income, $30-75k","@(df.income_in_thousands-30).clip(0, 45)",,0,0.0083,0.011,0.0147 "Piecewise Linear household income, $75k+, capped at $125k","@(df.income_in_thousands-75).clip(0, 50)",,0,0.0083,0.011,0.0147 "Density index up to 10, if 0 workers","@(df.workers==0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654 "Density index in excess of 10, if 0 workers",@(df.workers==0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766 "Density index up to 10, if 1+ workers","@(df.workers>0)*df.density_index.clip(0, 10)",,0,-0.2028,-0.3654,-0.3654 "Density index in excess of 10, if 1+ workers",@(df.workers>0)*(df.density_index-10).clip(0),,-0.0152,-0.1106,-0.1766,-0.1766 Constants,@1,,1.1865,-1.0846,-3.2502,-5.313 San Francisco county,county_name == 'San Francisco',,0.4259,0.4683,0.1458,0.1458 Solano county,county_name == 'Solano',,-0.566,-0.4429,-0.2372,-0.2372 Napa county,county_name == 'Napa',,-0.566,-0.4429,-0.2372,-0.2372 Sonoma county,county_name == 'Sonoma',,-0.566,-0.4429,-0.2372,-0.2372 Marin county,county_name == 'Marin',,-0.2434,0,0,0 "Retail accessibility (0.66*PK + 0.34*OP) by auto, if 0 workers",(workers==0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.0626,0.0626,0.0626,0.0626 "Retail accessibility (0.66*PK + 0.34*OP) by auto, if 1+ workers",(workers>0)*(0.66*AUTOPEAKRETAIL+0.34*AUTOOFFPEAKRETAIL),,0.1646,0.1646,0.1646,0.1646 "Retail accessibility (0.66*PK + 0.34*OP) by transit, if 0 workers",(workers==0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.3053,-0.3053,-0.3053,-0.3053 "Retail accessibility (0.66*PK + 0.34*OP) by transit, if 1+ workers",(workers>0)*(0.66*TRANSITPEAKRETAIL+0.34*TRANSITOFFPEAKRETAIL),,-0.5117,-0.5117,-0.5117,-0.5117 "Retail accessibility by non-motorized, if 0 workers",(workers==0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03 "Retail accessibility by non-motorized, if 1+ workers",(workers>0)*NONMOTORIZEDRETAIL,,-0.03,-0.03,-0.03,-0.03 "Auto time savings per worker (over walk or transit, max 120) to work",workTourAutoTimeSavings/workers,,0.4707,0.6142,0.5705,0.7693 \ No newline at end of file diff --git a/example/configs/cdap_1_person.csv b/example/configs/cdap_1_person.csv new file mode 100644 index 0000000000..24672e2050 --- /dev/null +++ b/example/configs/cdap_1_person.csv @@ -0,0 +1 @@ +Description,Expression,Mandatory,NonMandatory,Home Full-time worker alternative-specific constants,ptype == 1,1.378734579,0.622662391, Part-time worker alternative-specific constants,ptype == 2,-0.718823738,0.636032467, University student alternative-specific constants,ptype == 3,2.353595176,0.609709846, Non-working adult alternative-specific constants,ptype == 4,-999,0.594645386, Retired alternative-specific constants,ptype == 5,-999,0.408202071, Driving-age child who is in school alternative-specific constants,ptype == 6,2.330918685,-0.599119112, Pre-driving-age child who is in school alternative-specific constants,ptype == 7,3.295863529,0.57142434, Pre-driving-age child who is too young for school alternative-specific constants,ptype == 8,1.052531189,-0.837567776, Pre-driving-age child who is too young for school interaction with age 0 to 1,(ptype == 8) & (age >= 0) & (age <= 1),-0.4515,, Pre-driving-age child who is too young for school interaction with age 4 to 5,(ptype == 8) & (age >= 4) & (age <= 5),0.6107,, Pre-driving-age child who is in school interaction with age 6 to 9,(ptype == 7) & (age >= 6) & (age <= 9),-0.2943,, Pre-driving-age child who is in school interaction with age 13 to 15,(ptype == 7) & (age >= 13) & (age <= 15),-0.7141,-0.672, Full-time worker interaction with age less than 40,(ptype == 1) & (age < 40),0.2091,, Retired interaction with age more than 80,(ptype == 5) & (age > 80),,,0.7666 Full-time worker interaction with female gender,(ptype == 1) & (sex == 2),-0.1259,, Non-working adult interaction with female gender,(ptype == 4) & (sex == 2),-0.743,, Retired interaction with female,(ptype == 5) & (sex == 2),0.4769,, Full-time worker interaction with income less than $20k,(ptype == 1) & (income_in_thousands < 20),,,0.5313 Retired interaction with income less than $20k,(ptype == 5) & (income_in_thousands < 20),,,0.533 Part-time worker interaction with income less than $20k,(ptype == 2) & (income_in_thousands < 20),,,0.3232 Part-time worker interaction with income between $50k and $100k,(ptype == 2) & (income_in_thousands >= 50) & (income_in_thousands <= 100),,,-0.4032 Part-time worker interaction with income more than $100k,(ptype == 2) & (income_in_thousands < 100),,0.4207,-0.3534 Non-working adult interaction with income between $50k and $100k,(ptype == 4) & (income_in_thousands >= 50) & (income_in_thousands <= 100),,,-0.5602 Non-working adult interaction with income more than $100k,(ptype == 4) & (income_in_thousands < 100),,,-0.7188 Driving-age child who is in school interaction with less than $20k,(ptype == 6) & (income_in_thousands < 20),,,1.307 Driving-age child who is in school interaction income between $50k and $100k,(ptype == 6) & (income_in_thousands >= 50) & (income_in_thousands <= 100),,,-0.5031 Driving-age child who is in school interaction with income more than $100k,(ptype == 6) & (income_in_thousands < 100),,,-2.046 Pre-driving-age child who is too young for school interaction with income between $50k and $100k,(ptype == 8) & (income_in_thousands >= 50) & (income_in_thousands <= 100),,,-0.5708 Pre-driving-age child who is too young for school interaction with income more than $100k,(ptype == 8) & (income_in_thousands < 100),,,-0.6186 Full-time worker intraction with peak accessibility to all employment,(ptype == 1) * AUTOPEAKTOTAL,0.1212,, Part-time worker interaction with peak accessibility to all employment,(ptype == 2) * AUTOPEAKTOTAL,0.2004,, Non-working adult interaction with peak accessibility to all employment,(ptype == 4) * AUTOPEAKTOTAL,0.2314,, Retired interaction with peak accessibility to all employment,(ptype == 5) * AUTOPEAKTOTAL,0.2792,, Non-working adult interaction with off-peak accessibility to retail,(ptype == 4) * AUTOOFFPEAKRETAIL,,0.07207, Retired interaction with off-peak accessibility to retail,(ptype == 5) * AUTOOFFPEAKRETAIL,,0.07207, University student interaction with off-peak accessibility to retail,(ptype == 3) * AUTOOFFPEAKRETAIL,,0.07207, Driving-age child who is in school interaction with off-peak accessibility to retail,(ptype == 6) * AUTOOFFPEAKRETAIL,,0.08233, Pre-driving-age child who is in school interaction with off-peak accessibility to retail,(ptype == 7) * AUTOOFFPEAKRETAIL,,0.08233, Pre-driving-age child who is too young for school interaction with off-peak accessibility to retail,(ptype == 8) * AUTOOFFPEAKRETAIL,,0.08233, Full-time worker interaction with usual work location is home,#(ptype == 1) * usualWorkLocationIsHome,-1.758,,0.1813 Part-time worker interaction with usual work location is home,#(ptype == 2) * usualWorkLocationIsHome,-1.758,,0.1813 Full-time worker interaction with no usual work location,#(ptype == 1) * noUsualWorkLocation,-0.5935,, Part-time worker interaction with no usual work location,#(ptype == 2) * noUsualWorkLocation,-0.5935,, Driving-age child who is in school interaction with no usual school location,#(ptype == 6) * noUsualWorkLocation,-0.866,, Pre-driving age child who is in school interaction with no usual school location,#(ptype == 7) * noUsualWorkLocation,-0.866,, Non-working adult interaction with more cars than workers,(ptype == 4) & (auto_ownership > workers),0.6515,0.8168, Retired interaction with more cars than workers,(ptype == 5) & (auto_ownership > workers),2.992,1.056, Pre-driving-age child who is too young for school interaction with more cars than workers,(ptype == 8) & (auto_ownership > workers),,0.2991, Full-time worker interaction with fewer cars than workers,(ptype == 1) & (auto_ownership < workers),,,0.5039 Non-working adult interaction with fewer cars than workers,(ptype == 4) & (auto_ownership < workers),,,0.8965 Retired interaction with fewer cars than workers,(ptype == 5) & (auto_ownership < workers),,,0.5496 Driving-age child who is in school interaction with fewer cars than workers,(ptype == 6) & (auto_ownership < workers),,,0.6475 Pre-driving-age child who is in school interaction with fewer cars than workers,(ptype == 7) & (auto_ownership < workers),,,0.5862 Pre-driving-age child who is too young for school interaction with fewer cars than workers,(ptype == 8) & (auto_ownership < workers),,,0.5061 \ No newline at end of file diff --git a/example/configs/cdap_2_person.csv b/example/configs/cdap_2_person.csv new file mode 100644 index 0000000000..fb9959944f --- /dev/null +++ b/example/configs/cdap_2_person.csv @@ -0,0 +1 @@ +Description,Expression,Mandatory,NonMandatory,Home Full-time worker interaction with full-time worker,ptype == 11,0.141,1.123,1.626 Full-time worker interaction with part-time worker,ptype == 12 or ptype == 21,0.08845,0.4947,0.7407 Full-time worker interaction with university student,ptype == 31 or ptype == 13,0.4273,0.5523,1.183 Full-time worker interaction with non-working adult,ptype == 41 or ptype == 14,,0.02186,0.9436 Full-time worker interaction with retired,ptype == 51 or ptype == 15,,0.3115,1.298 Full-time worker interaction with driving-age child who is in school,ptype == 61 or ptype == 16,0.3842,0.4095,2.064 Full-time worker interaction with pre-driving-age child who is in school,ptype == 71 or ptype == 17,0.2623,0.6008,1.501 Full-time worker interaction with pre-driving-age child who is too young for school,ptype == 81 or ptype == 18,0.5118,0.751,0.9912 Part-time worker interaction with part-time worker,ptype == 22,1.135,1.032,0.8911 Part-time worker interaction with university student,ptype == 23 or ptype == 32,0.173,0.3355,1.642 Part-time worker interaction with non-working adult,ptype == 24 or ptype == 42,,0.7477,0.7057 Part-time worker interaction with retired,ptype == 25 or ptype == 52,,0.09831,0.463 Part-time worker interaction with driving-age child who is in school,ptype == 26 or ptype == 62,1.103,0.495,3.057 Part-time worker interaction with pre-driving-age child who is in school,ptype == 27 or ptype == 72,0.3079,0.8984,0.7685 Part-time worker interaction with pre-driving-age child who is too young for school,ptype == 28 or ptype == 82,0.5074,1.452,1.07 University student interaction with university student,ptype == 33,0.8726,1.054,1.018 University student interaction with non-working adult,ptype == 34 or ptype == 43,,0.193,1.781 University student interaction with retired,ptype == 35 or ptype == 53,,0.4065,0.4835 University student interaction with driving-age child who is in school,ptype == 36 or ptype == 63,-0.0021,1.62,1.546 University student interaction with pre-driving-age child who is in school,ptype == 37 or ptype == 73,0.2975,0.5165,1.552 University student interaction with pre-driving-age child who is too young for school,ptype == 38 or ptype == 83,0.2254,0.8973,1.34 Non-working adult interaction with non-working adult,ptype == 44,,0.6984,1.352 Non-working adult interaction with retired,ptype == 45 or ptype == 54,,0.1864,1.209 Non-working adult interaction with driving-age child who is in school,ptype == 46 or ptype == 64,,0.6801,0.5243 Non-working adult interaction with pre-driving-age child who is in school,ptype == 47 or ptype == 74,,0.5646,0.8112 Non-working adult interaction with pre-driving-age child who is too young for school,ptype == 48 or ptype == 84,,1.164,1.167 Retired interaction with retired,ptype == 55,,0.7291,1.407 Retired interaction with driving-age child who is in school,ptype == 56 or ptype == 65,,0.2919,0.8632 Retired interaction with pre-driving-age child who is in school,ptype == 57 or ptype == 75,,0.2919,0.8632 Retired interaction with pre-driving-age child who is too young for school,ptype == 58 or ptype == 85,,0.2919,0.8632 Driving-age child who is in school interaction with driving-age child who is in school,ptype == 66,0.4794,1.512,2.198 Driving-age child who is in school interaction with pre-driving-age child who is in school,ptype == 67 or ptype == 76,0.5151,1.422,0.977 Driving-age child who is in school interaction with pre-driving-age child who is too young for school,ptype == 68 or ptype == 86,0.5516,1.273,1.467 Pre-driving-age child who is in school interaction with pre-Pre-driving-age child who is in school,ptype == 77,0.9731,1.553,2.8 Pre-driving-age child who is in school interaction with pre-driving-age child who is too young for school,ptype == 78 or ptype == 87,0.5961,0.6184,1.434 Pre-driving-age child who is too young for school interaction with pre-driving-age child who is too young for school,ptype == 88,1.651,0.8771,1.378 Mandatory pattern unavailable for retired person,#retiredA,-999,, Mandatory pattern unavailable for retired person,#retiredB,-999,, Mandatory pattern unavailable for nonworking adult person type,#nonWorkingAdultA,-999,, Mandatory pattern unavailable for nonworking adult person type,#nonWorkingAdultB,-999,, \ No newline at end of file diff --git a/example/configs/destination_choice.csv b/example/configs/destination_choice.csv new file mode 100644 index 0000000000..9f239eafdb --- /dev/null +++ b/example/configs/destination_choice.csv @@ -0,0 +1,10 @@ +Description,Expression,university,highschool,gradeschool,escortkids,escortnokids,shopping,eatout,othmaint,social,othdiscr,workbased +Sample of alternatives correction factor,"min(dcSoaCorrections,60)",1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000 +"Distance, piecewise linear from 0 to 1 miles","if(distance<1.0,distance,1.0)",-3.2451,-0.9523,-1.6419,-0.1499,-0.1499,0.0000,-0.5609,0.0000,-0.7841,-0.1677,-0.7926 +"Distance, piecewise linear from 1 to 2 miles","if(distance<2.0,distance-1.0,1.0)",-2.7011,-0.5700,-0.5700,-0.1499,-0.1499,0.0000,-0.5609,0.0000,-0.7841,-0.1677,-0.7926 +"Distance, piecewise linear from 2 to 5 miles","if(distance<5.0,distance-2.0,3.0)",-0.5707,-0.5700,-0.5700,-0.8671,-0.8671,-0.5655,-0.3192,-0.6055,-0.3485,-0.4955,-0.5197 +"Distance, piecewise linear from 5 to 15 miles","if(distance<15.0,distance-5.0,10.0)",-0.5002,-0.1930,-0.2031,-0.2137,-0.2137,-0.1832,-0.1238,-0.1093,-0.1306,-0.1193,-0.2045 +"Distance, piecewise linear for 15+ miles",distance-15.0,-0.0730,-0.1882,-0.0460,-0.2137,-0.2137,-0.1832,-0.1238,-0.1093,-0.1306,-0.1193,-0.2045 +Mode choice logsum,mcLogsum,0.5358,0.5358,0.5358,0.6755,0.6755,0.6755,0.6755,0.6755,0.6755,0.6755,0.5136 +Size variable,sizeTerm,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000,1.0000 +No attractions,"if(sizeTerm==0,1,0)",-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000,-999.0000 \ No newline at end of file diff --git a/example/configs/destination_choice_alternatives_sample.csv b/example/configs/destination_choice_alternatives_sample.csv new file mode 100644 index 0000000000..2a33dac443 --- /dev/null +++ b/example/configs/destination_choice_alternatives_sample.csv @@ -0,0 +1,9 @@ +Description,Expression,worklow,workmed,workhigh,workveryhigh,university,highschool,gradeschool,escortkids,escortnokids,shopping,eatout,othmaint,social,othdiscr,workbased +"Distance, piecewise linear from 0 to 1 miles",@df.distance.clip(1),-0.8428,-0.8428,-0.8428,-0.8428,-3.2451,-0.9523,-1.6419,-0.1499,-0.1499,0,-0.5609,0,-0.7841,-0.1677,-0.7926 +"Distance, piecewise linear from 1 to 2 miles","@(df.distance-1).clip(0,1)",-0.3104,-0.3104,-0.3104,-0.3104,-2.7011,-0.57,-0.57,-0.1499,-0.1499,0,-0.5609,0,-0.7841,-0.1677,-0.7926 +"Distance, piecewise linear from 2 to 5 miles","@(df.distance-2).clip(0,3)",-0.3783,-0.3783,-0.3783,-0.3783,-0.5707,-0.57,-0.57,-0.8671,-0.8671,-0.5655,-0.3192,-0.6055,-0.3485,-0.4955,-0.5197 +"Distance, piecewise linear from 5 to 15 miles","@(df.distance-5).clip(0,10)",-0.1285,-0.1285,-0.1285,-0.1285,-0.5002,-0.193,-0.2031,-0.2137,-0.2137,-0.1832,-0.1238,-0.1093,-0.1306,-0.1193,-0.2045 +"Distance, piecewise linear for 15+ miles",@(df.distance-15.0).clip(0),-0.0917,-0.0917,-0.0917,-0.0917,-0.073,-0.1882,-0.046,-0.2137,-0.2137,-0.1832,-0.1238,-0.1093,-0.1306,-0.1193,-0.2045 +Size variable,@(df.income_segment==1)*df.size_low,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +No attractions,@(df.income_segment==1)*df.size_low == 0,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999,-999 +Destination taz is home taz,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 \ No newline at end of file diff --git a/example/configs/destination_choice_size_terms.csv b/example/configs/destination_choice_size_terms.csv new file mode 100644 index 0000000000..6ef694785a --- /dev/null +++ b/example/configs/destination_choice_size_terms.csv @@ -0,0 +1,16 @@ +purpose,segment,TOTHH,RETEMPN,FPSEMPN,HEREMPN,OTHEMPN,AGREMPN,MWTEMPN,AGE0519,HSENROLL,COLLFTE,COLLPTE +work,low,0,0.129,0.193,0.383,0.12,0.01,0.164,0,0,0,0 +work,med,0,0.12,0.197,0.325,0.139,0.008,0.21,0,0,0,0 +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,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 +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,shopping,0,1,0,0,0,0,0,0,0,0,0 +eatOut,eatOut,0,0.742,0,0.258,0,0,0,0,0,0,0 +othMaint,othMaint,0,0.482,0,0.518,0,0,0,0,0,0,0 +social,social,0,0.522,0,0.478,0,0,0,0,0,0,0 +othDiscr,othDiscr,0.252,0.212,0,0.272,0.165,0,0,0,0.098,0,0 +atwork,atwork,0,0.742,0,0.258,0,0,0,0,0,0,0 diff --git a/example/configs/mandatory_tour_frequency.csv b/example/configs/mandatory_tour_frequency.csv new file mode 100644 index 0000000000..0021c24429 --- /dev/null +++ b/example/configs/mandatory_tour_frequency.csv @@ -0,0 +1,100 @@ +Description,Expression,work1,work2,school1,school2,work_and_school +Full-time worker alternative-specific constants,ptype == 1,0,-3.3781,,, +Part-time worker alternative-specific constants,ptype == 2,0,-3.0476,,, +University student alternative-specific constants,ptype == 3,2.166,-1.3965,0,-3.7429,0.1073 +Non-working adult alternative-specific constants,ptype == 4,,,,, +Retired alternative-specific constants,ptype == 5,,,,, +Driving-age child alternative-specific constants,ptype == 6,,,0,-3.136,-4.4362 +Pre-driving age child who is in school alternative-specific constants,ptype == 7,,,0,-3.9703, +Female - Full-time worker interaction,(ptype == 1) & female,0,-0.2255,0.1592,,-0.3442 +Female - Part-time worker interaction,(ptype == 2) & female,0,-0.2255,0.1592,,-0.3442 +Female - University student interaction,(ptype == 3) & female,0.1737,-0.2255,0.1592,0.114,-0.3442 +Female - Non-working adult interaction,(ptype == 4) & female,0,-0.2255,0.1592,, +Female - Retired interaction,(ptype == 5) & female,0,-0.2255,0.1592,, +Female - Driving-age child interaction,(ptype == 6) & female,0.1737,,0,0.114,-0.3442 +Female - Pre-driving age child who is in school interaction,(ptype == 7) & female,0.1737,,0,0.114, +Under 35 - Full-time worker interaction,(ptype == 1) & (age <= 35),0,-0.1375,0.7218,,0.9761 +Under 35 - Part-time worker interaction,(ptype == 2) & (age <= 35),0,-0.1375,0.7218,,0.9761 +Under 35 - University student interaction,(ptype == 3) & (age <= 35),-0.4629,-0.1375,0,1.275,0.9761 +Under 35 - Non-working adult interaction,(ptype == 4) & (age <= 35),0,-0.1375,0.7218,, +Can walk to work - Full-time worker interaction,(ptype == 1) & (distance_to_work < 3),,0.5268,,, +Can walk to work - Part-time worker interaction,(ptype == 2) & (distance_to_work < 3),,0.5268,,, +Can walk to work - University student interaction,(ptype == 3) & (distance_to_work < 3),,0.5268,,, +Can walk to work - Non-working adult interaction,(ptype == 4) & (distance_to_work < 3),,0.5268,,, +Can walk to work - Retired interaction,(ptype == 5) & (distance_to_work < 3),,0.5268,,, +Can walk to school - University student interaction,(ptype == 3) & (distance_to_school < 3),,,,0.7114, +Can walk to school - Driving-age child interaction,(ptype == 6) & (distance_to_school < 3),,,,0.7114, +Can walk to school - Pre-driving age child who is in school interaction,(ptype == 7) & (distance_to_school < 3),,,,0.7114, +Can walk to work or school - Full-time worker interaction,(ptype == 1) & (distance_to_work < 3 | distance_to_school < 3),,,,,0.1391 +Can walk to work or school - Part-time worker interaction,(ptype == 2) & (distance_to_work < 3 | distance_to_school < 3),,,,,0.1391 +Can walk to work or school - University student interaction,(ptype == 3) & (distance_to_work < 3 | distance_to_school < 3),,,,,0.1391 +Can walk to work or school - Driving-age child interaction,(ptype == 6) & (distance_to_work < 3 | distance_to_school < 3),,,,,0.1391 +Round trip auto time to work - Full-time worker interaction,(ptype == 1) * roundtrip_auto_time_to_work,,-0.0035,,,-0.0031 +Round trip auto time to work - Part-time worker interaction,(ptype == 2) * roundtrip_auto_time_to_work,,-0.0035,,,-0.0031 +Round trip auto time to work - University student interaction,(ptype == 3) * roundtrip_auto_time_to_work,,-0.0035,,,-0.0031 +Round trip auto time to work - Non-working adult interaction,(ptype == 4) * roundtrip_auto_time_to_work,,-0.0035,,, +Round trip auto time to work - Retired,(ptype == 5) * roundtrip_auto_time_to_work,,-0.0035,,, +Round trip auto time to school - University student interaction,(ptype == 3) * roundtrip_auto_time_to_school,,,,-0.0034,-0.0031 +Round trip auto time to school - Driving-age child interaction,(ptype == 6) * roundtrip_auto_time_to_school,,,,-0.0034,-0.0031 +Round trip auto time to school - Pre-driving age child who is in school interaction,(ptype == 7) * roundtrip_auto_time_to_school,,,,-0.0034, +Student is employed - University student interaction,(ptype == 3) & student_is_employed,3.014,3.014,,,3.014 +Student is employed - Driving-age child interaction,(ptype == 6) & student_is_employed,3.014,3.014,,,3.014 +Non-student goes to school - Full-time worker interaction,(ptype == 1) & nonstudent_to_school,,,3.883,,3.883 +Non-student goes to school - Part-time worker interaction,(ptype == 2) & nonstudent_to_school,,,3.883,,3.883 +Non-student goes to school - Non-working adult interaction,(ptype == 4) & nonstudent_to_school,,,3.883,, +Non-student goes to school - Retired interaction,(ptype == 5) & nonstudent_to_school,,,3.883,, +No cars in household - Full-time worker interaction,(ptype == 1) & (auto_ownership == 0),,-1.306,,,-1.302 +No cars in household - Part-time worker interaction,(ptype == 2) & (auto_ownership == 0),,-1.306,,,-1.302 +No cars in household - University student interaction,(ptype == 3) & (auto_ownership == 0),,-1.306,,-1.413,-1.302 +No cars in household - Non-working adult interaction,(ptype == 4) & (auto_ownership == 0),,-1.306,,, +No cars in household - Retired interaction,(ptype == 5) & (auto_ownership == 0),,-1.306,,, +No cars in household - Driving-age student interaction,(ptype == 6) & (auto_ownership == 0),,,,-1.413,-1.302 +No cars in household - Pre-driving age child who is in school interaction,(ptype == 7) & (auto_ownership == 0),,,,-1.413, +Fewer cars than drivers in household - University student interaction,(ptype == 3) & (auto_ownership < drivers),,,,-0.5759, +Fewer cars than drivers in household - Driving-age student interaction,(ptype == 6) & (auto_ownership < drivers),,,,-0.5759, +Fewer cars than drivers in household - Pre-driving age child who is in school interaction,(ptype == 7) & (auto_ownership < drivers),,,,-0.5759, +Number of preschool children in household - Full-time worker interaction,(ptype == 1) * (num_young_children),0,-0.1478,-0.1335,,-0.1251 +Number of preschool children in household - Part-time worker interaction,(ptype == 2) * (num_young_children),0,-0.1478,-0.1335,,-0.1251 +Number of preschool children in household - University student interaction,(ptype == 3) * (num_young_children),0.2191,-0.1478,0,-0.5577,-0.1251 +Number of preschool children in household - Non-working adult interaction,(ptype == 4) * (num_young_children),0,-0.1478,-0.1335,, +Number of preschool children in household - Retired interaction,(ptype == 5) * (num_young_children),0,-0.1478,-0.1335,, +Number of preschool children in household - Driving-age student interaction,(ptype == 6) * (num_young_children),0.2191,,0,-0.5577,-0.1251 +Number of preschool children in household - Pre-driving age child who is in school interaction,(ptype == 7) * (num_young_children),0.2191,,0,-0.5577, +Number of non-workers in the household - Full-time worker interaction,(ptype == 1) * non_workers,,,0.2574,, +Number of non-workers in the household - Part-time worker interaction,(ptype == 2) * non_workers,,,0.2574,, +Household income higher than $50k - Full-time worker interaction,(ptype == 1) & (income_in_thousands > 50),0,,0.0347,,0.0347 +Household income higher than $50k - Part-time worker interaction,(ptype == 2) & (income_in_thousands > 50),0,,0.0347,,0.0347 +Household income higher than $50k - University student interaction,(ptype == 3) & (income_in_thousands > 50),-0.0528,-0.0528,0,,-0.0528 +Household income higher than $50k - Non-working adult interaction,(ptype == 4) & (income_in_thousands > 50),0,,0.0347,, +Household income higher than $50k - Retired interaction,(ptype == 5) & (income_in_thousands > 50),0,,0.0347,, +Household income higher than $50k - Driving-age student interaction,(ptype == 6) & (income_in_thousands > 50),-0.0528,,0,,-0.0528 +Household income higher than $50k - Pre-driving age child who is in school interaction,(ptype == 7) & (income_in_thousands > 50),-0.0528,,0,, +Non-family household - Full-time worker interaction,(ptype == 1) & non_family,0,,-0.25,,-0.25 +Non-family household - Part-time worker interaction,(ptype == 2) & non_family,0,,-0.25,,-0.25 +Non-family household - University student interaction,(ptype == 3) & non_family,-0.1792,-0.1792,0,,-0.1792 +Non-family household - Non-working adult interaction,(ptype == 4) & non_family,0,,-0.25,, +Non-family household - Retired interaction,(ptype == 5) & non_family,0,,-0.25,, +Non-family household - Driving-age student interaction,(ptype == 6) & non_family,-0.1792,,0,,-0.1792 +Non-family household - Pre-driving age child who is in school interaction,(ptype == 7) & non_family,-0.1792,,0,, +Number of children under 16 not at school - Full-time worker interaction,(ptype == 1) * num_under16_not_at_school,,0.1804,,,-0.1955 +Number of children under 16 not at school - Part-time worker interaction,(ptype == 2) * num_under16_not_at_school,,0.1804,,,-0.1955 +Number of children under 16 not at school - University student interaction,(ptype == 3) * num_under16_not_at_school,,0.1804,,0.0866,-0.1955 +Number of children under 16 not at school - Non-working adult interaction,(ptype == 4) * num_under16_not_at_school,,0.1804,,, +Number of children under 16 not at school - Retired,(ptype == 5) * num_under16_not_at_school,,0.1804,,, +Number of children under 16 not at school - Driving-age student interaction,(ptype == 6) * num_under16_not_at_school,,,,0.0866,-0.1955 +Number of children under 16 not at school - Pre-driving age child who is in school interaction,(ptype == 7) * num_under16_not_at_school,,,,0.0866, +Home is in urban area - Full-time worker interaction,(ptype == 1) & home_is_urban,0,0.2308,-0.1361,,-0.3509 +Home is in urban area - Part-time worker interaction,(ptype == 2) & home_is_urban,0,0.2308,-0.1361,,-0.3509 +Home is in urban area - University student interaction,(ptype == 3) & home_is_urban,-0.2831,0.2308,0,0.317,-0.3509 +Home is in urban area - Non-working adult interaction,(ptype == 4) & home_is_urban,0,0.238,-0.1361,, +Home is in urban area - Retired interaction,(ptype == 5) & home_is_urban,0,0.2308,-0.1361,, +Home is in urban area - Driving-age student interaction,(ptype == 6) & home_is_urban,-0.2831,,0,0.317,-0.3509 +Home is in urban area - Pre-driving age child who is in school interaction,(ptype == 7) & home_is_urban,-0.2831,,0,0.317, +Unavailable: Full-time worker,ptype == 1,,,,-999, +Unavailable: Part-time worker,ptype == 2,,,,-999, +Unavailable: Non-working adult,ptype == 4,,,,-999,-999 +Unavailable: Retired,ptype == 5,,,,-999,-999 +Unavailable: Driving-age child,ptype == 6,-999,-999,,, +Unavailable: Pre-driving age child who is in school,ptype == 7,,-999,,,-999 +Unavailable: Work tours for those with no usual work location,~(workplace_taz > -1),-999,-999,,,-999 +Unavailalbe: School tours for those with no usual school location,~(school_taz > -1),,,-999,-999,-999 \ No newline at end of file diff --git a/example/configs/non_mandatory_tour_frequency.csv b/example/configs/non_mandatory_tour_frequency.csv new file mode 100644 index 0000000000..49499f514c --- /dev/null +++ b/example/configs/non_mandatory_tour_frequency.csv @@ -0,0 +1,205 @@ +Description,Expression,full,part,university,nonwork,retired,driving,school,preschool +Total Number of Tours = 0 (No Prior Tours),(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0),-999,-999,-999,-999,-999,-999,-999,-999 +Total Number of Tours = 0 (1 or more Prior Tours),(tot_tours == 0) & ((num_mand > 0) | (num_joint_tours > 0)),0,0,0,0,0,0,0,0 +Total Number of Tours = 1,tot_tours == 1,-7.3572,-7.6391,-6.2138,-8.9791,-8.5684,-7.1506,-7.1506,-5.759 +Total Number of Tours = 2,tot_tours == 2,-10.647,-10.4557,-8.908,-12.0248,-12.7416,-11.1214,-11.1214,-11.517 +Total Number of Tours = 3,tot_tours == 3,-13.5005,-14.0176,-12.3261,-14.8516,-15.0978,-13.175,-13.175,-17.276 +Total Number of Tours = 4,tot_tours == 4,-16.3965,-16.9717,-15.8114,-17.7037,-19.5439,-999,-999,-23.035 +Total Number of Tours = 5,tot_tours == 5,-19.6843,-999,-999,-999,-20.7897,-999,-999,-999 +Total Number of Tours = 6+,tot_tours > 5,-999,-999,-999,-999,-999,-999,-999,-999 +Number of Mandatory tours & tour frequency =0,num_mand*(tot_tours == 0),0,0,0,0,0,0,0,2.491 +Number of Mandatory tours & tour frequency =1,num_mand*(tot_tours == 1),0,-0.239,-0.1852,-0.6766,0,-0.234,-0.234,0.903 +Number of Mandatory tours & tour frequency =2,num_mand*(tot_tours == 2),-0.8887,-1.8208,-0.8753,-1.0518,-5.0196,-0.9231,-0.9231,0 +Number of Mandatory tours & tour frequency =3,num_mand*(tot_tours == 3),-2.3343,-2.5923,-1.6158,-1.0518,-5.0196,-6.5835,-6.5835,1.022 +Number of Mandatory tours & tour frequency =4,num_mand*(tot_tours == 4),-2.3343,-2.5923,-999,-999,-999,-999,-999,0.769 +Number of Mandatory tours & tour frequency = 5+,num_mand*(tot_tours > 4),-2.3343,-2.5923,-999,-999,-999,-999,-999,0 +Number of Joint tours & tour frequency =0,num_joint_tours*(tot_tours == 0),0,0,0,0,0,0,0,0 +Number of Joint tours & tour frequency =1,num_joint_tours*(tot_tours == 1),0,0,0,-0.1699,0,-0.2162,-0.2162,0 +Number of Joint tours & tour frequency =2,num_joint_tours*(tot_tours == 2),0,-1.1986,-0.3153,-0.4285,-0.95,-0.3587,-0.3587,0 +Number of Joint tours & tour frequency =3,num_joint_tours*(tot_tours == 3),0,-1.1986,-0.7351,-0.6551,-7.143,-4.2701,-4.2701,0 +Number of Joint tours & tour frequency =4,num_joint_tours*(tot_tours == 4),0,-1.1986,-999,-1.0411,-999,-999,-999,0 +Number of Joint tours & tour frequency = 5+,num_joint_tours*(tot_tours > 4),0,-999,-999,-1.0411,-999,-999,-999,0 +Number of Joint Shopping tours,num_shop_j,0,0,-0.713,-0.2391,-0.8072,0,0,0 +Number of Joint Maintenance tours,num_main_j,0,0,0,0,0,0,0,0 +Number of Joint Eating Out tours,num_eat_j,-0.5866,0,0,-0.7727,0,0,0,0 +Number of Joint Visit tours,num_visi_j,0,0,0,0,0,0,0,0 +Number of Joint Discretionary tours,num_disc_j,0,0,0.6713,0,0,0,0,0 +"Logged Maximum Residual Window, tour frequency =0",max_window*(tot_tours == 0),0,0,1.1858,0,0,0,0,0 +"Logged Maximum Residual Window, tour frequency =1",max_window*(tot_tours == 1),1.2562,1.5748,1.4842,1.7637,1.8357,1.3298,1.3298,0 +"Logged Maximum Residual Window, tour frequency =2",max_window*(tot_tours == 2),1.2868,2.0026,1.4842,1.7928,2.2707,1.3759,1.3759,0 +"Logged Maximum Residual Window, tour frequency =3",max_window*(tot_tours == 3),1.3993,2.0026,1.4842,1.7928,4.4023,3.2808,3.2808,0 +"Logged Maximum Residual Window, tour frequency =4",max_window*(tot_tours == 4),1.3993,2.0026,1.4842,1.7928,4.4023,3.2808,3.2808,0 +"Logged Maximum Residual Window, tour frequency =5+",max_window*(tot_tours > 4),1.3993,2.0026,1.4842,1.7928,4.4023,3.2808,3.2808,0 +Dummy for Mediumlow Income group (20K-50K) & tour frequency=1,(20 < income_in_thousands <= 50) & (tot_tours == 1),0.4981,0.5981,0,0.5709,0,0,0,0 +Dummy for Mediumlow Income group (20K-50K) & tour frequency=2,(20 < income_in_thousands <= 50) & (tot_tours == 2),0.8345,0.9178,0,0.8315,0,0,0,0 +Dummy for Mediumlow Income group (20K-50K) & tour frequency=3,(20 < income_in_thousands <= 50) & (tot_tours == 3),1.0213,1.7539,0,0.8315,0,0,0,0 +Dummy for Mediumlow Income group (20K-50K) & tour frequency=4,(20 < income_in_thousands <= 50) & (tot_tours == 4),1.0213,1.7539,0,0.8315,0,0,0,0 +Dummy for Mediumlow Income group (20K-50K) & tour frequency=5+,(20 < income_in_thousands <= 50) & (tot_tours > 4),1.0213,1.7539,0,0.8315,0,0,0,0 +Dummy for MediumHigh Income group (50K-100K) & tour frequency=1,(50 < income_in_thousands <= 100) & (tot_tours == 1),0.4981,0.8682,0.1109,0.7426,0,0,0,0 +Dummy for MediumHigh Income group (50K-100K) & tour frequency=2,(50 < income_in_thousands <= 100) & (tot_tours == 2),0.8345,1.5362,0.3914,0.8546,0,0,0,0 +Dummy for MediumHigh Income group (50K-100K) & tour frequency=3,(50 < income_in_thousands <= 100) & (tot_tours == 3),1.0213,1.9331,0.6137,1.0792,0,0,0,0 +Dummy for MediumHigh Income group (50K-100K) & tour frequency=4,(50 < income_in_thousands <= 100) & (tot_tours == 4),1.0213,1.9331,0.6137,1.0792,0,0,0,0 +Dummy for MediumHigh Income group (50K-100K) & tour frequency=5+,(50 < income_in_thousands <= 100) & (tot_tours > 4),1.0213,1.9331,0.6137,1.0792,0,0,0,0 +Dummy for High Income group (>100K) & tour frequency=1,(100 < income_in_thousands) & (tot_tours == 1),0.5189,0.8682,0.3986,1.0633,0,0,0,0 +Dummy for High Income group (>100K) & tour frequency=2,(100 < income_in_thousands) & (tot_tours == 2),1.1336,1.5362,0.8009,1.0633,0,0,0,0 +Dummy for High Income group (>100K) & tour frequency=3,(100 < income_in_thousands) & (tot_tours == 3),1.3899,1.9331,0.8254,1.7742,0,0,0,0 +Dummy for High Income group (>100K) & tour frequency=4,(100 < income_in_thousands) & (tot_tours == 4),1.3899,1.9331,0.8254,2.3941,0,0,0,0 +Dummy for High Income group (>100K) & tour frequency=5+,(100 < income_in_thousands) & (tot_tours > 4),1.3899,1.9331,0.8254,2.3941,0,0,0,0 +Dummy for Mediumlow Income group (20K-50K) & shopping tour,(20 < income_in_thousands <= 50) * shopping,0,0.4421,0.5693,0.7734,1.0949,0,0,0 +Dummy for Mediumhigh Income group (50K-100K) & shopping tour,(50 < income_in_thousands <= 100) * shopping,0,0.4421,0.5693,0.8906,1.0949,0.2443,0.2443,0 +Dummy for High Income group (>100K) & shopping tour,(100 < income_in_thousands) * shopping,0,0.7066,0.5693,0.9776,1.0949,0.2443,0.2443,0 +Dummy for Mediumlow Income group (20K-50K) & maintenance tour,(20 < income_in_thousands <= 50) * othmaint,0,0.6763,0,0,0.7648,0,0,0 +Dummy for Mediumhigh Income group (50K-100K) & maintenance tour,(50 < income_in_thousands <= 100) * othmaint,0,0.6763,0,0,0.7648,0.3982,0.3982,0 +Dummy for High Income group (>100K) & maintenance tour,(100 < income_in_thousands) * othmaint,0,0.6763,0,0,1.3795,0.3982,0.3982,0 +Dummy for Mediumlow Income group (20K-50K) & Eating out tour,(20 < income_in_thousands <= 50) * eatout,0,0,0,0.2766,0.9769,0,0,0 +Dummy for Mediumhigh Income group (50K-100K) & Eating out tour,(50 < income_in_thousands <= 100) * eatout,0.5581,0,-0.7207,0.4631,1.181,0.4916,0.4916,0 +Dummy for High Income group (>100K) & Eating out tour,(100 < income_in_thousands) * eatout,0.5581,0,-0.7207,0.7086,1.4842,0.4916,0.4916,0 +Dummy for Mediumlow Income group (20K-50K) & Discretionary tour,(20 < income_in_thousands <= 50) * othdiscr,0,0.296,0,0.1707,1.0095,0.9169,0.9169,0 +Dummy for Mediumhigh Income group (50K-100K) & Discretionary tour,(50 < income_in_thousands <= 100) * othdiscr,0.2565,0.296,0,0.5009,1.0095,1.405,1.405,0 +Dummy for High Income group (>100K) & Discretionary tour,(100 < income_in_thousands) * othdiscr,0.2565,0.296,0,0.8846,1.0095,2.327,2.327,0 +Dummy for Mediumlow Income group (20K-50K) & Visiting tour,(20 < income_in_thousands <= 50) * social,0,-0.6868,0,-0.267,0,0,0,0 +Dummy for Mediumhigh Income group (50K-100K) & Visiting tour,(50 < income_in_thousands <= 100) * social,-0.2423,-0.6868,-0.3694,-0.267,-0.4368,0.2858,0.2858,0 +Dummy for High Income group (>100K) & Visiting tour,(100 < income_in_thousands) * social,-0.2423,-0.6868,-0.3694,-0.9449,-0.5137,0.2858,0.2858,0 +Dummy for Female & tour frequency =1,female & (tot_tours == 1),-0.0766,0,0.0973,0.3902,-0.9348,0,0,0 +Dummy for Female & tour frequency =2,female & (tot_tours == 2),-0.1062,0,0.2361,0.5323,-1.3028,0,0,0 +Dummy for Female & tour frequency =3,female & (tot_tours == 3),-0.3274,0,1.9002,0.7452,-2.266,0,0,0 +Dummy for Female & tour frequency =4,female & (tot_tours == 4),-0.3274,0,1.9002,1.1294,-2.266,0,0,0 +Dummy for Female & tour frequency =5,female & (tot_tours == 5),-0.3274,0,1.9002,1.1294,-2.266,0,0,0 +Dummy for Female & Escorting Tour,female * escort,0.1824,0,0,0,0,0,0,0 +Dummy for Female & Shopping Tour,female * shopping,0,0.4524,0,0,0.9688,0,0,0 +Dummy for Female & Maintenance Tour,female * othmaint,0,0,0,-0.2464,0.7424,0,0,0 +Dummy for Female & EatingOut Tour,female * eatout,0,0,-0.6568,0,0,0,0,0 +Dummy for Female & Discretionary Tour,female * othdiscr,0,0.3072,-0.3266,0,0.4954,0,0,0 +Dummy for zero car ownership & tour frequency =1,no_cars & (tot_tours == 1),-0.3486,-0.5498,-0.581,-0.3623,0,-0.6369,-0.6369,0 +Dummy for zero car ownership & tour frequency =2,no_cars & (tot_tours == 2),-0.3486,-0.5498,-0.581,-1.272,0,-0.6369,-0.6369,0 +Dummy for zero car ownership & tour frequency =3,no_cars & (tot_tours == 3),-0.3486,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for zero car ownership & tour frequency =4,no_cars & (tot_tours == 4),-0.3486,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for zero car ownership & tour frequency =5+,no_cars & (tot_tours > 4),-0.3486,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for Car Shortage vs Workers & tour frequency =1,(car_sufficiency < 0) & (tot_tours == 1),0,-0.5498,-0.581,-0.3623,0,-0.6369,-0.6369,0 +Dummy for Car Shortage vs Workers & tour frequency =2,(car_sufficiency < 0) & (tot_tours == 2),0,-0.5498,-0.581,-1.272,0,-0.6369,-0.6369,0 +Dummy for Car Shortage vs Workers & tour frequency =3,(car_sufficiency < 0) & (tot_tours == 3),0,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for Car Shortage vs Workers & tour frequency =4,(car_sufficiency < 0) & (tot_tours == 4),0,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for Car Shortage vs Workers & tour frequency =5+,(car_sufficiency < 0) & (tot_tours > 4),0,-0.5498,-0.581,-1.9307,0,-0.6369,-0.6369,0 +Dummy for Car Surplus vs Workers & tour frequency =1,(car_sufficiency > 0) & (tot_tours == 1),0.1304,0,0,0.7738,0.7965,0.2902,0.2902,0 +Dummy for Car Surplus vs Workers & tour frequency =2,(car_sufficiency > 0) & (tot_tours == 2),0.1304,0,0,0.7738,2.1302,2.0352,2.0352,0 +Dummy for Car Surplus vs Workers & tour frequency =3,(car_sufficiency > 0) & (tot_tours == 3),0.1304,0,0,0.7738,2.1302,2.0352,2.0352,0 +Dummy for Car Surplus vs Workers & tour frequency =4,(car_sufficiency > 0) & (tot_tours == 4),0.1304,0,0,0.7738,2.1302,2.0352,2.0352,0 +Dummy for Car Surplus vs Workers & tour frequency =5+,(car_sufficiency > 0) & (tot_tours > 4),0.1304,0,0,0.7738,2.1302,2.0352,2.0352,0 +Dummy for Presence of Non-Worker(other than modeled person) & tour frequency =1,has_non_worker & (tot_tours == 1),0,0,-0.8506,-0.3763,0.224,0,0,0 +Dummy for Presence of Non-Worker(other than modeled person) & tour frequency =2,has_non_worker & (tot_tours == 2),0,0,-1.1804,-0.719,0.2436,-0.6571,-0.6571,0 +Dummy for Presence of Non-Worker(other than modeled person) & tour frequency =3,has_non_worker & (tot_tours == 3),0,0,-1.1804,-1.0229,0.62,-1.4044,-1.4044,0 +Dummy for Presence of Non-Worker(other than modeled person) & tour frequency =4,has_non_worker & (tot_tours == 4),0,0,-1.1804,-1.0229,3.3742,-1.4044,-1.4044,0 +Dummy for Presence of Non-Worker(other than modeled person) & tour frequency =5,has_non_worker & (tot_tours == 5),0,0,-1.1804,-1.0229,3.3742,-1.4044,-1.4044,0 +Dummy for Presence of Retiree(other than modeled person) & tour frequency =1,has_retiree & (tot_tours == 1),0,0,0,-0.464,-0.4458,0,0,0 +Dummy for Presence of Retiree(other than modeled person) & tour frequency =2,has_retiree & (tot_tours == 2),0,0,0,-0.4795,-0.5315,0,0,0 +Dummy for Presence of Retiree(other than modeled person) & tour frequency =3,has_retiree & (tot_tours == 3),0,0,0,-0.4795,-0.5315,0,0,0 +Dummy for Presence of Retiree(other than modeled person) & tour frequency =4,has_retiree & (tot_tours == 4),0,0,0,-0.4795,-0.5315,0,0,0 +Dummy for Presence of Retiree(other than modeled person) & tour frequency =5,has_retiree & (tot_tours == 5),0,0,0,-0.4795,-0.5315,0,0,0 +Dummy for Presence of PreSchool Kid (other than modeled person) in Household & tour frequency =1,has_preschool_kid & (tot_tours == 1),0,-0.1559,-0.9961,-0.7161,0,0,0,0 +Dummy for Presence of PreSchool Kid (other than modeled person) in Household & tour frequency =2,has_preschool_kid & (tot_tours == 2),0,-0.5681,-1.9096,-0.7161,0,0,0,0 +Dummy for Presence of PreSchool Kid (other than modeled person) in Household & tour frequency =3,has_preschool_kid & (tot_tours == 3),0,-0.5681,-2.8469,-0.7161,0,0,0,0 +Dummy for Presence of PreSchool Kid (other than modeled person) in Household & tour frequency =4,has_preschool_kid & (tot_tours == 4),0,-0.5681,-2.8469,-0.7161,0,0,0,0 +Dummy for Presence of PreSchool Kid (other than modeled person) in Household & tour frequency =5,has_preschool_kid & (tot_tours == 5),0,-0.5681,-2.8469,-0.7161,0,0,0,0 +Dummy for Presence of Predriving School Kid (other than modeled person) in Household & tour frequency =1,has_school_kid & (tot_tours == 1),0,0,0,0.1486,0,-0.3219,-0.3219,0 +Dummy for Presence of Predriving School Kid (other than modeled person) in Household & tour frequency =2,has_school_kid & (tot_tours == 2),0,0,0,0.484,0,-1.0874,-1.0874,0 +Dummy for Presence of Predriving School Kid (other than modeled person) in Household & tour frequency =3,has_school_kid & (tot_tours == 3),0,0,0,0.484,0,-1.0874,-1.0874,0 +Dummy for Presence of Predriving School Kid (other than modeled person) in Household & tour frequency =4,has_school_kid & (tot_tours == 4),0,0,0,0.484,0,-1.0874,-1.0874,0 +Dummy for Presence of Predriving School Kid (other than modeled person) in Household & tour frequency =5,has_school_kid & (tot_tours == 5),0,0,0,0.484,0,-1.0874,-1.0874,0 +Dummy for Presence of Full time Worker (other than modeled person) & Escorting tour ,has_full_time * escort,0,0,0,0.3947,0,0,0,-0.893 +Dummy for Presence of Part time Worker (other than modeled person) & Escorting tour ,has_part_time * escort,0,0,-1.8213,-0.5861,0,0,0,0 +Dummy for Presence of Non-Worker (other than modeled person) & Escorting tour ,has_non_worker * escort,-0.4815,-0.5263,0,0,0,0,0,0.89 +Dummy for Presence of Retiree (other than modeled person) & Escorting tour ,has_retiree * escort,-0.808,-0.7516,0,0,0,0,0,0 +Dummy for Presence of University Student (other than modeled person) & Escorting tour ,has_university * escort,0,0,0,0,0,0,0,0 +Dummy for Presence of Driving School Kid (other than modeled person) & Escorting tour ,has_driving_kid * escort,0.3601,0.4164,0,0,0,0,0,0 +Dummy for Presence of Pre-Driving School Kid (other than modeled person) & Escorting tour ,has_school_kid * escort,1.3974,1.5795,0.9489,1.3773,1.4903,0,0,0 +Dummy for Presence of Pre-School Kid (other than modeled person) & Escorting tour ,has_preschool_kid * escort,0.6842,0.5414,2.1465,0.7194,0.5027,0,0,0 +Dummy for At home Pre-Driving School Kid & Escorting tour ,has_school_kid_at_home * escort,-0.2746,0,0,-1.148,0,0,0,0 +Dummy for At homef Pre-School Kid & Escorting tour ,has_preschool_kid_at_home * escort,-1.5675,0,0,-0.1373,0,0,0,0 +Dummy for Presence of Full time Worker (other than modeled person) & Shopping tour ,has_full_time * shopping,-0.3059,0,-0.7728,0,-0.3609,0,0,0 +Dummy for Presence of Part time Worker (other than modeled person) & Shopping tour ,has_part_time * shopping,-0.1541,0,-0.5199,0,0,0,0,1.155 +Dummy for Presence of Non-Worker (other than modeled person) & Shopping tour ,has_non_worker * shopping,-0.416,0,0,0,0,0,0,0.808 +Dummy for Presence of Retiree (other than modeled person) & Shopping tour ,has_retiree * shopping,0,0,0,0,0,0,0,0 +Dummy for Presence of University Student (other than modeled person) & Shopping tour ,has_university * shopping,0,0,0,0,0,0,0,0 +Dummy for Presence of Driving School Kid (other than modeled person) & Shopping tour ,has_driving_kid * shopping,0,0,0,0,0,0,0,0 +Dummy for Presence of Pre-Driving School Kid (other than modeled person) & Shopping tour ,has_school_kid * shopping,0,0,0,0,0,0,0,0 +Dummy for Presence of Pre-School Kid (other than modeled person) & Shopping tour ,has_preschool_kid * shopping,-0.208,0,1.3135,0,0,0,0,0 +Dummy for At home Pre-Driving School Kid & Shopping tour ,has_school_kid_at_home * shopping,0,0,0,0,0,0,0,0 +Dummy for At homef Pre-School Kid & Shopping tour ,has_preschool_kid_at_home * shopping,0,0,0,0,0,0,0,0 +Dummy for Presence of Full time Worker (other than modeled person) & Maintenance tour ,has_full_time * othmaint,-0.1685,-0.3131,0,0,0,0,0,0 +Dummy for Presence of Part time Worker (other than modeled person) & Maintenance tour ,has_part_time * othmaint,-0.1584,-0.5621,0,0,0,0,0,0 +Dummy for Presence of Non-Worker(other than modeled person) & Maintenance tour ,has_non_worker * othmaint,-0.3237,0,0,0,0,0,0,0 +Dummy for Presence of Retiree (other than modeled person) & Maintenance tour ,has_retiree * othmaint,0,0,0,0,0,0,0,0 +Dummy for Presence of University Student (other than modeled person) & Maintenance tour ,has_university * othmaint,0,0,0,0,0,0,0,0 +Dummy for Presence of Driving School Kid (other than modeled person) & Maintenance tour ,has_driving_kid * othmaint,0,0,0,0,0,0,0,0 +Dummy for Presence of Pre-Driving School Kid (other than modeled person) & Maintenance tour ,has_school_kid * othmaint,0,0,0.3863,0,0,0,0,0 +Dummy for Presence of Pre-School Kid (other than modeled person) & Maintenance tour ,has_preschool_kid * othmaint,0,0,0.9694,0,0,0,0,0 +Dummy for At home Pre-Driving School Kid & Maintenance tour ,has_school_kid_at_home * othmaint,0,0,0,0,0,0,0,0 +Dummy for At homef Pre-School Kid & Maintenance tour ,has_preschool_kid_at_home * othmaint,0,0,0,0,0,0,0,0 +Dummy for Presence of Full time Worker (other than modeled person) & Eating Out tour ,has_full_time * eatout,-0.3571,0,-0.5251,-0.4667,-0.788,0,0,0 +Dummy for Presence of Part time Worker (other than modeled person) & Eating Out tour ,has_part_time * eatout,0,0,-1.9795,0,-0.788,0,0,1.037 +Dummy for Presence of Non-Worker (other than modeled person) & Eating Out tour ,has_non_worker * eatout,-0.2014,-0.6545,0,-0.4976,-0.788,0,0,1.157 +Dummy for Presence of Retiree (other than modeled person) & Eating Out tour ,has_retiree * eatout,-0.5708,-1.389,0,-0.6911,-0.9282,0,0,0 +Dummy for Presence of University Student (other than modeled person) & Eating Out tour ,has_university * eatout,0,-1.4318,-0.6529,0,0,0,0,0 +Dummy for Presence of Driving School Kid (other than modeled person) & Eating Out tour ,has_driving_kid * eatout,0,0,0,0,0,-0.6377,-0.6377,0 +Dummy for Presence of Pre-Driving School Kid (other than modeled person) & Eating Out tour ,has_school_kid * eatout,0,0,0,0,0,-1.5698,-1.5698,0 +Dummy for Presence of Pre-School Kid (other than modeled person) & Eating Out tour ,has_preschool_kid * eatout,-0.4225,0,0,0,0,-0.2987,-0.2987,0 +Dummy for At home Pre-Driving School Kid & Eating Out tour ,has_school_kid_at_home * eatout,0,0,0,-0.3926,0,0,0,0 +Dummy for At homef Pre-School Kid & Eating Out tour ,has_preschool_kid_at_home * eatout,0,0,0,-0.3926,0,0,0,0 +Dummy for Presence of Full time Worker (other than modeled person) & Discretionary tour ,has_full_time * othdiscr,-0.667,0,-0.4833,-0.3545,-0.4835,0,0,0 +Dummy for Presence of Part time Worker (other than modeled person) & Discretionary tour ,has_part_time * othdiscr,-0.2102,0,0,-0.3545,0,0,0,0 +Dummy for Presence of Non-Worker (other than modeled person) & Discretionary tour ,has_non_worker * othdiscr,-0.4281,-1.0371,0.9781,0,-0.5603,0,0,0.791 +Dummy for Presence of Retiree (other than modeled person) & Discretionary tour ,has_retiree * othdiscr,-0.9104,0,0,0,0,0,0,0 +Dummy for Presence of University Student (other than modeled person) & Discretionary tour ,has_university * othdiscr,-0.8551,0,-0.6542,0,0,-1.2834,-1.2834,0 +Dummy for Presence of Driving School Kid (other than modeled person) & Discretionary tour ,has_driving_kid * othdiscr,-0.3963,0,0,0,0,-0.9202,-0.9202,0 +Dummy for Presence of Pre-Driving School Kid (other than modeled person) & Discretionary tour ,has_school_kid * othdiscr,-0.3959,0,0,0,0,0,0,0 +Dummy for Presence of Pre-School Kid (other than modeled person) & Discretionary tour ,has_preschool_kid * othdiscr,-0.5081,0,0,0,0,0,0,0 +Dummy for At home Pre-Driving School Kid & Discretionary tour ,has_school_kid_at_home * othdiscr,-0.4703,0,0,0,0,0,0,0 +Dummy for At homef Pre-School Kid & Discretionary tour ,has_preschool_kid_at_home * othdiscr,-0.4703,0,0,0,0,0,0,0 +Walk Access to Retail & Tour Frequency =1,NONMOTORIZEDRETAIL * (tot_tours == 1),0,0.0899,0,0.0713,0.0616,0,0,0 +Walk Access to Retail & Tour Frequency =2,NONMOTORIZEDRETAIL * (tot_tours == 2),0,0.1447,0,0.1256,0.0616,0,0,0 +Walk Access to Retail & Tour Frequency =3,NONMOTORIZEDRETAIL * (tot_tours == 3),0,0.3479,0,0.1508,0.0616,0,0,0 +Walk Access to Retail & Tour Frequency =4,NONMOTORIZEDRETAIL * (tot_tours == 4),0,0.3479,0,0.1508,0.0616,0,0,0 +Walk Access to Retail & Tour Frequency =5+,NONMOTORIZEDRETAIL * (tot_tours > 4),0,0.3479,0,0.1508,0.0616,0,0,0 +Transit Access to Retail & Tour Frequency =1,TRANSITOFFPEAKRETAIL * (tot_tours == 1),0.0226,0,0.0664,0,0,0,0,0 +Transit Access to Retail & Tour Frequency =2,TRANSITOFFPEAKRETAIL * (tot_tours == 2),0.0226,0,0.0664,0,0,0,0,0 +Transit Access to Retail & Tour Frequency =3,TRANSITOFFPEAKRETAIL * (tot_tours == 3),0.0226,0,0.0664,0,0,0,0,0 +Transit Access to Retail & Tour Frequency =4,TRANSITOFFPEAKRETAIL * (tot_tours == 4),0.0226,0,0.0664,0,0,0,0,0 +Transit Access to Retail & Tour Frequency =5+,TRANSITOFFPEAKRETAIL * (tot_tours > 4),0.0226,0,0.0664,0,0,0,0,0 +Auto Access to Retail & Tour Frequency =1,AUTOOFFPEAKRETAIL * (tot_tours == 1),0,0,0,0,0,0.1004,0.1004,0 +Auto Access to Retail & Tour Frequency =2,AUTOOFFPEAKRETAIL * (tot_tours == 2),0,0,0,0,0,0.1004,0.1004,0 +Auto Access to Retail & Tour Frequency =3,AUTOOFFPEAKRETAIL * (tot_tours == 3),0,0,0,0,0,0.1004,0.1004,0 +Auto Access to Retail & Tour Frequency =4,AUTOOFFPEAKRETAIL * (tot_tours == 4),0,0,0,0,0,0.1004,0.1004,0 +Auto Access to Retail & Tour Frequency =5+,AUTOOFFPEAKRETAIL * (tot_tours > 4),0,0,0,0,0,0.1004,0.1004,0 +Walk Access to Retail & Escorting ,NONMOTORIZEDRETAIL * escort,0.0451,0,0,0,0,0,0,0 +Transit Access to Retail & Escorting ,TRANSITOFFPEAKRETAIL * escort,0,0,0,0,0,0,0,0 +Auto Access to Retail & Escorting ,AUTOOFFPEAKRETAIL * escort,0,0,0,0,0,0,0,0 +Walk Access to Retail & Shopping ,NONMOTORIZEDRETAIL * shopping,0.033,0,0.0972,0.0598,0,0,0,0 +Transit Access to Retail & Shopping ,TRANSITOFFPEAKRETAIL * shopping,0,0,0,0,0,0,0,0 +Auto Access to Retail & Shopping ,AUTOOFFPEAKRETAIL * shopping,0.1067,0,0,0,0,0,0,0 +Walk Access to Retail & Maintenance ,NONMOTORIZEDRETAIL * othmaint,0,0,0,0,0,0,0,0 +Transit Access to Retail & Maintenance ,TRANSITOFFPEAKRETAIL * othmaint,0,0,0.0314,0,0,0,0,0 +Auto Access to Retail & Maintenance ,AUTOOFFPEAKRETAIL * othmaint,0.0749,0,0,0.0956,0,0,0,0 +Walk Access to Retail & Eating Out ,NONMOTORIZEDRETAIL * eatout,0.145,0,0,0,0,0,0,0 +Transit Access to Retail & Eating Out ,TRANSITOFFPEAKRETAIL * eatout,0,0,0,0,0,0,0,0 +Auto Access to Retail & Eating Out ,AUTOOFFPEAKRETAIL * eatout,0,0,0.1018,0,0,0,0,0 +Walk Access to Retail & Discretionary ,NONMOTORIZEDRETAIL * othdiscr,0.0567,0,0,0.0772,0,0,0,0 +Transit Access to Retail & Discretionary ,TRANSITOFFPEAKRETAIL * othdiscr,0,0,0,0,0,0,0,0 +Auto Access to Retail & Discretionary ,AUTOOFFPEAKRETAIL * othdiscr,0.0844,0,0.094,0,0,0,0,0 +Urban Areatype & Tour Frequency =1,home_is_urban & (tot_tours == 1),0,0,-1.1648,0,0,0,0,0 +Urban Areatype & Tour Frequency =2,home_is_urban & (tot_tours == 2),0,0,-2.3177,0,0,0,0,0 +Urban Areatype & Tour Frequency =3,home_is_urban & (tot_tours == 3),0,0,-2.5027,0,0,0,0,0 +Urban Areatype & Tour Frequency =4,home_is_urban & (tot_tours == 4),0,0,-2.5027,0,0,0,0,0 +Urban Areatype & Tour Frequency =5+,home_is_urban & (tot_tours > 4),0,0,-2.5027,0,0,0,0,0 +Urban Areatype & Escorting tour,home_is_urban * escort,-0.4316,-0.3929,0.8516,0,0,0,0,0 +Urban Areatype &Shopping tour,home_is_urban * shopping,0,0,0.533,0,0,0,0,0 +Urban Areatype & Maintenance tour,home_is_urban * othmaint,0,0,1.0316,0,0,1.0394,1.0394,0 +Urban Areatype & EatingOut tour,home_is_urban * eatout,0,0,0.68,0,0,0,0,0 +Urban Areatype & Discretionary tour,home_is_urban * othdiscr,0,0,0.9563,0,0,0,0,0 +1 Escort Tour Constant,escort == 1,0.0298,0.5272,1.7028,-0.0629,-0.3992,-0.4934,-0.4934,0.3622 +2+ Escort Tours Constant,escort >= 2,0.7402,1.5987,2.8379,0.9273,0.5175,1.4155,1.4155,2.2219 +1+ Shopping Tours Constant,shopping >= 1,0.4774,0.7569,1.8403,0.4683,0.5947,0.532,0.532,1.6919 +1+ Maintenance Tours Constant,othmaint >= 1,0.1202,0.5533,0.3348,-0.0653,0.1046,-0.4344,-0.4344,0.6788 +1+ Eating Out Tours Constant,eatout >= 1,0.0097,0.6914,2.0723,-0.1429,0.0245,-0.0242,-0.0242,0.9612 +1+ Visting Tours Constant,social >= 1,0.0522,0.1405,1.2172,-0.1272,0.2789,0.2367,0.2367,0.4424 +1+ Other Discretionary Tours Constant,othdiscr >= 1,0.7412,0.7989,1.3389,0.3334,0.4282,-0.2602,-0.2602,1.4935 +Dummy for 0-auto household & Escorting Tour,escort * no_cars,-2,-2,-2,-2,-2,-2,-2,-2 \ No newline at end of file diff --git a/example/configs/non_mandatory_tour_frequency_alternatives.csv b/example/configs/non_mandatory_tour_frequency_alternatives.csv new file mode 100644 index 0000000000..1c0052f963 --- /dev/null +++ b/example/configs/non_mandatory_tour_frequency_alternatives.csv @@ -0,0 +1,97 @@ +escort,shopping,othmaint,othdiscr,eatout,social +0,0,0,0,0,0 +0,0,0,1,0,0 +0,0,0,0,0,1 +0,0,0,1,0,1 +0,0,0,0,1,0 +0,0,0,1,1,0 +0,0,0,0,1,1 +0,0,0,1,1,1 +0,0,1,0,0,0 +0,0,1,1,0,0 +0,0,1,0,0,1 +0,0,1,1,0,1 +0,0,1,0,1,0 +0,0,1,1,1,0 +0,0,1,0,1,1 +0,0,1,1,1,1 +0,1,0,0,0,0 +0,1,0,1,0,0 +0,1,0,0,0,1 +0,1,0,1,0,1 +0,1,0,0,1,0 +0,1,0,1,1,0 +0,1,0,0,1,1 +0,1,0,1,1,1 +0,1,1,0,0,0 +0,1,1,1,0,0 +0,1,1,0,0,1 +0,1,1,1,0,1 +0,1,1,0,1,0 +0,1,1,1,1,0 +0,1,1,0,1,1 +0,1,1,1,1,1 +1,0,0,0,0,0 +1,0,0,1,0,0 +1,0,0,0,0,1 +1,0,0,1,0,1 +1,0,0,0,1,0 +1,0,0,1,1,0 +1,0,0,0,1,1 +1,0,0,1,1,1 +1,0,1,0,0,0 +1,0,1,1,0,0 +1,0,1,0,0,1 +1,0,1,1,0,1 +1,0,1,0,1,0 +1,0,1,1,1,0 +1,0,1,0,1,1 +1,0,1,1,1,1 +1,1,0,0,0,0 +1,1,0,1,0,0 +1,1,0,0,0,1 +1,1,0,1,0,1 +1,1,0,0,1,0 +1,1,0,1,1,0 +1,1,0,0,1,1 +1,1,0,1,1,1 +1,1,1,0,0,0 +1,1,1,1,0,0 +1,1,1,0,0,1 +1,1,1,1,0,1 +1,1,1,0,1,0 +1,1,1,1,1,0 +1,1,1,0,1,1 +1,1,1,1,1,1 +2,0,0,0,0,0 +2,0,0,1,0,0 +2,0,0,0,0,1 +2,0,0,1,0,1 +2,0,0,0,1,0 +2,0,0,1,1,0 +2,0,0,0,1,1 +2,0,0,1,1,1 +2,0,1,0,0,0 +2,0,1,1,0,0 +2,0,1,0,0,1 +2,0,1,1,0,1 +2,0,1,0,1,0 +2,0,1,1,1,0 +2,0,1,0,1,1 +2,0,1,1,1,1 +2,1,0,0,0,0 +2,1,0,1,0,0 +2,1,0,0,0,1 +2,1,0,1,0,1 +2,1,0,0,1,0 +2,1,0,1,1,0 +2,1,0,0,1,1 +2,1,0,1,1,1 +2,1,1,0,0,0 +2,1,1,1,0,0 +2,1,1,0,0,1 +2,1,1,1,0,1 +2,1,1,0,1,0 +2,1,1,1,1,0 +2,1,1,0,1,1 +2,1,1,1,1,1 diff --git a/example/configs/settings.yaml b/example/configs/settings.yaml index 05cf2cdb08..c80b37fa89 100644 --- a/example/configs/settings.yaml +++ b/example/configs/settings.yaml @@ -1,6 +1,11 @@ store: mtc_asim.h5 -households_sample_size: 100000 +# area_types less than this are considered urban +urban_threshold: 4 +cbd_threshold: 2 +rural_threshold: 6 + +households_sample_size: 1000 county_map: San Francisco: 1 @@ -12,3 +17,34 @@ county_map: Napa: 7 Sonoma: 8 Marin: 9 + +employment_map: + 1: "full" + 2: "part" + 3: "not" + 4: "child" + +student_map: + 1: "high" + 2: "college" + 3: "not" + +person_type_map: + 1: "full" + 2: "part" + 3: "university" + 4: "nonwork" + 5: "retired" + 6: "driving" + 7: "school" + 8: "preschool" + +household_type_map: + 0: "null" + 1: "family_married" + 2: "family_male" + 3: "family_female" + 4: "nonfamily_male_alone" + 5: "nonfamily_male_notalone" + 6: "nonfamily_female_alone" + 7: "nonfamily_female_notalone" diff --git a/example/configs/tour_departure_and_duration_alternatives.csv b/example/configs/tour_departure_and_duration_alternatives.csv new file mode 100644 index 0000000000..05f02b7964 --- /dev/null +++ b/example/configs/tour_departure_and_duration_alternatives.csv @@ -0,0 +1,191 @@ +start,end +5,5 +5,6 +5,7 +5,8 +5,9 +5,10 +5,11 +5,12 +5,13 +5,14 +5,15 +5,16 +5,17 +5,18 +5,19 +5,20 +5,21 +5,22 +5,23 +6,6 +6,7 +6,8 +6,9 +6,10 +6,11 +6,12 +6,13 +6,14 +6,15 +6,16 +6,17 +6,18 +6,19 +6,20 +6,21 +6,22 +6,23 +7,7 +7,8 +7,9 +7,10 +7,11 +7,12 +7,13 +7,14 +7,15 +7,16 +7,17 +7,18 +7,19 +7,20 +7,21 +7,22 +7,23 +8,8 +8,9 +8,10 +8,11 +8,12 +8,13 +8,14 +8,15 +8,16 +8,17 +8,18 +8,19 +8,20 +8,21 +8,22 +8,23 +9,9 +9,10 +9,11 +9,12 +9,13 +9,14 +9,15 +9,16 +9,17 +9,18 +9,19 +9,20 +9,21 +9,22 +9,23 +10,10 +10,11 +10,12 +10,13 +10,14 +10,15 +10,16 +10,17 +10,18 +10,19 +10,20 +10,21 +10,22 +10,23 +11,11 +11,12 +11,13 +11,14 +11,15 +11,16 +11,17 +11,18 +11,19 +11,20 +11,21 +11,22 +11,23 +12,12 +12,13 +12,14 +12,15 +12,16 +12,17 +12,18 +12,19 +12,20 +12,21 +12,22 +12,23 +13,13 +13,14 +13,15 +13,16 +13,17 +13,18 +13,19 +13,20 +13,21 +13,22 +13,23 +14,14 +14,15 +14,16 +14,17 +14,18 +14,19 +14,20 +14,21 +14,22 +14,23 +15,15 +15,16 +15,17 +15,18 +15,19 +15,20 +15,21 +15,22 +15,23 +16,16 +16,17 +16,18 +16,19 +16,20 +16,21 +16,22 +16,23 +17,17 +17,18 +17,19 +17,20 +17,21 +17,22 +17,23 +18,18 +18,19 +18,20 +18,21 +18,22 +18,23 +19,19 +19,20 +19,21 +19,22 +19,23 +20,20 +20,21 +20,22 +20,23 +21,21 +21,22 +21,23 +22,22 +22,23 +23,23 \ No newline at end of file diff --git a/example/configs/tour_departure_and_duration_mandatory.csv b/example/configs/tour_departure_and_duration_mandatory.csv new file mode 100644 index 0000000000..6a2afd916a --- /dev/null +++ b/example/configs/tour_departure_and_duration_mandatory.csv @@ -0,0 +1,64 @@ +Description,Expression,Coefficient +Free-flow round trip auto time shift effects - departure,roundtrip_auto_time_to_work * start,0.00114 +Free-flow round trip auto time shift effects - duration,roundtrip_auto_time_to_work * duration,0.00221 +Part-time worker departure shift effects,(ptype == 2) * start,0.06736 +Non-working adult duration shift effects,(ptype == 4) * duration,0.1207 +University student departure shift effects,(ptype == 3) * start,0.05747 +Household income departure shift effects,income_in_thousands * start,0.00021 +Destination in CBD departure shift effects,workplace_in_cbd * start,0.04717 +Destination in CBD duration shift effects,workplace_in_cbd * duration,0.08679 +subsequent tour must start after previous tour ends,(start < end_of_previous_tour) & (tour_num == 2),-999 +First of 2+ work tours departure shift effects,(tour_num == 1) * start,0.3033 +First of 2+ work tours duration shift effects,(tour_num == 1) * duration,0.1861 +Subsequent 2+ work departure tours shift effects,(tour_num == 2) * start,0.5381 +Subsequent 2+ work duration tours shift effects,(tour_num == 2) * duration,0.3174 +Household income -- Early departure interaction,(income_in_thousands > 100) & (start < 6),0.4854 +Household income -- Late arrival interaction,(income_in_thousands > 100) & (end > 22),0.3839 +Destination in CBD -- Early departure interaction,workplace_in_cbd & (start < 6),0.4566 +Destination in CBD -- Late arrival interaction,workplace_in_cbd & (end > 22),0.2334 +Rural household -- Early departure interaction,home_is_rural & (start < 6),0.4039 +Rural household -- Late arrival interaction,home_is_rural & (end > 22),0.3451 +Full-time worker -- duration < 9 hours interaction,(ptype == 1) & (duration < 9),1.257 +Full-time worker -- 10 to 12 departure interaction,(ptype == 1) & (start > 9) & (start < 13),0.5182 +Part-time worker -- 13 to 15 arrival interaction,(ptype == 2) & (end > 12) & (end < 16),0.5433 +First of 2+ work tours- duration<8 hrs,(tour_num == 1) & (duration < 8),1.98 +Subsequent of 2+ work tours- duration<8 hrs,(tour_num == 2) & (duration < 8),2.582 +Work+school tours by worker- duration<8 hrs,(mandatory_tour_frequency == 'work_and_school') & is_worker & (duration < 8),0.9126 +School+work tours by student- duration<8 hrs,(mandatory_tour_frequency == 'work_and_school') & is_student & (duration < 8),2.582 +Mode Choice Logsum,mode_choice_logsum,1.027 +Previously-scheduled tour ends in this departure hour,prev_tour_end == start,0.8935 +Previously-scheduled tour begins in this arrival hour,prev_tour_begin == end,1.334 +Adjacent window exists before this departure hour - first tour interaction,@@adjWindowBeforeThisHourAlt,0.1771 +Adjacent window exists afetr this arrival hour - first tour interaction,@@adjWindowAfterThisHourAlt,0.3627 +Adjacent window exists before this departure hour - second+ tour interaction,@@adjWindowBeforeThisHourAlt,0.2123 +Adjacent window exists after this arrival hour - second+ tour interaction,@@adjWindowAfterThisHourAlt,0.1012 +Remaining work/school tours to be scheduled / number of unscheduled hours,1 / @@remainingHoursAvailableAlt,18.68 +Departure Constants -- Early (up to 5),start < 6,0.95273 +Departure Constants -- AM peak 1 (6),start == 6,0.61618 +Departure Constants -- AM peak 2 (7),start == 7,0 +Departure Constants -- AM peak 3 (8),start == 8,0.25471 +Departure Constants -- AM peak 4 (9),start == 9,1.25135 +Departure Constants -- Midday 1 (10 to 12),(start > 9) & (start < 13),1.70587 +Departure Constants -- Midday 2 (13 to 15),(start > 12) & (start < 16),1.69357 +Departure Constants -- PM peak (16 to 18),(start > 15) & (start < 19),1.43999 +Departure Constants -- Evening (19 to 21),(start > 18) & (start < 22),1.61051 +Departure Constants -- Late (22 and later),start > 21,2.88342 +Arrival Constants -- Early (up to 6),end < 7,0 +Arrival Constants -- AM peak (7 to 9),(end > 6) & (end < 10),1.85452 +Arrival Constants -- Midday 1 (10 to 12),(end > 9) & (end < 13),0.49597 +Arrival Constants -- Midday 2 (13 to 14),(end > 12) & (end < 15),0.37855 +Arrival Constants -- PM peak 1 (15),end == 15,0 +Arrival Constants -- PM peak 2 (16),end == 16,0.27608 +Arrival Constants -- PM peak 3 (17),end == 17,0.69959 +Arrival Constants -- PM peak 4 (18),end == 18,0.79929 +Arrival Constants -- Evening (19 to 21),(end > 18) & (end < 22),0.10357 +Arrival Constants -- Late (22 and later),end > 21,0.96596 +Duration Constants -- 0 to 2 hours,duration < 3,2.52827 +Duration Constants -- 3 to 4 hours,(duration > 2) & (duration < 5),0.91897 +Duration Constants -- 5 to 6 hours,(duration > 4) & (duration < 7),0.71855 +Duration Constants -- 7 to 8 hours,(duration > 6) & (duration < 9),0.13962 +Duration Constants -- 9 hours,duration == 9,0.05571 +Duration Constants -- 10 hours,duration == 10,0 +Duration Constants -- 11 hours,duration == 11,0.3478 +Duration Constants -- 12 to 13 hours,(duration > 11) & (duration < 14),1.00822 +Duration Constants -- 14 to 18 hours,(duration > 13) & (duration < 19),1.70186 \ No newline at end of file diff --git a/example/configs/tour_departure_and_duration_nonmandatory.csv b/example/configs/tour_departure_and_duration_nonmandatory.csv new file mode 100644 index 0000000000..b940c997ac --- /dev/null +++ b/example/configs/tour_departure_and_duration_nonmandatory.csv @@ -0,0 +1,91 @@ +Description,,Expression,Coefficient +subsequet tour must start after previous tour ends,subsequentTour,start < end_of_previous_tour,999 +Free-flow round trip auto time shift effects - duration,,roundtrip_auto_time_to_work * duration,0.00474 +Shopping tour - departure shift effects,tourPurposeIsShopping,"(tour_type == ""shopping"") * start",0.06015 +Shopping tour - duration shift effects,tourPurposeIsShopping,"(tour_type == ""shopping"") * duration",0.1208 +Maintenance tour - departure shift effects,tourPurposeIsMaint,"(tour_type == ""oth_maint"") * start",0.1489 +Maintenance tour - departure shift effects,tourPurposeIsMaint,"(tour_type == ""oth_maint"") * duration",0.08372 +Visit tour - departure shift effects,tourPurposeIsVisit,"(tour_type == ""social"") * start",0.09688 +Visit tour - departure shift effects,tourPurposeIsVisit,"(tour_type == ""social"") * duration",0.1638 +Eat Out tour - departure shift effects,tourPurposeIsEatOut,"(tour_type == ""eatout"") * start",0.07549 +School child age 16+ - departure shift effects,studentDrivingAge,(ptype == 6) * start,0.07266 +School child age 16+ - duration shift effects,studentDrivingAge,(ptype == 6) * duration,0.2095 +School child age under 16 - departure shift effects,studentNonDrivingAge,(ptype == 7) * start,0.04657 +School child age under 16 - duration shift effects,studentNonDrivingAge,(ptype == 7) * duration,0.3272 +Destination in CBD - duration shift effects,destinationInCBD,duration,0.1067 +Number of mandatory tours - departure shift effects,,personMandatoryTotal * start,0.04673 +Number of joint tours - departure shift effects,,personJointTotal * start,0.05208 +Number of escort tours - departure shift effects,,personEscortTotal * start,0.02013 +Number of idividual non-mandatory tours (excluding escort) - departure shift effects,,personNonMandatoryTotalNoEscort * start,0.03896 +First of 2+ tours for same purpose - departure shift effect,firstTour,start,0.2364 +subsequent of 2+ tours for same purpose - duration shift effect,subsequentTour,duration,0.1731 +Maintenance tour - depart before 7,tourPurposeIsMaint,"(tour_type == ""oth_maint"") & (start < 7)",0.8826 +Shopping tour - depart before 8,tourPurposeIsShopping,"(tour_type == ""shopping"" & (start < 8)",1.037 +Shopping tour - arrive after 22,,"(tour_type == ""shopping"" & (end > 22)",0.6027 +School child under 16 - arrive after 22,studentNonDrivingAge,(ptype == 7) & (end > 22),1.18 +University student - arrive after 22,universityStudent,(ptype == 3) & (end > 22),0.5466 +Shopping tour - duration < 2 hours,tourPurposeIsShopping,"(tour_type == ""shopping"") & (duration < 2)",0.5168 +Discretionary tour - duration < 2 hours,tourPurposeIsDiscr,"(tour_type == ""othdisc"") & (duration < 2)",0.6974 +Adult with children in HH - arrive 19 - 21,personIsAdult * ( numChildrenInHH > 0 ),( end > 18 ) * ( end < 22 ),0.336 +Mode Choice Logsum,0,mode_choice_logsum,0 +Some previously-scheduled tour ends in this departure hour,,prev_tour_end == start,0.4562 +Some previously-scheduled tour begins in this arrival hour,,prev_tour_begin == end,0.3992 +Adjacent window exists before this departure hour - first tour interaction,firstTour,@@adjWindowBeforeThisHourAlt,0.00844 +Adjacent window exists afetr this arrival hour - first tour interaction,firstTour,@@adjWindowAfterThisHourAlt,0.0257 +Adjacent window exists before this departure hour - second+ tour interaction,subsequentTour,@@adjWindowBeforeThisHourAlt,0.0593 +Adjacent window exists after this arrival hour - second+ tour interaction,subsequentTour,@@adjWindowAfterThisHourAlt,0.02734 +Remaining individual non-mandatory tours to be scheduled / number of unscheduled hours,,@@remainingInmToursToAvailableHoursRatioAlt,13.63 +Departure Constants -- Early (up to 5),escortTour==0,"(tour_type != ""escort"") & (start < 6)",1.74014 +Departure Constants -- AM peak 1 (6),escortTour==0,"(tour_type != ""escort"") & (start == 6)",0.65416 +Departure Constants -- AM peak 2 (7),escortTour==0,"(tour_type != ""escort"") & (start == 7)",0.55428 +Departure Constants -- AM peak 3 (8),escortTour==0,"(tour_type != ""escort"") & (start == 8)",1.05056 +Departure Constants -- AM peak 4 (9),escortTour==0,"(tour_type != ""escort"") & (start == 9)",0.97157 +Departure Constants -- Midday 1 (10 to 12),escortTour==0,"(tour_type != ""escort"") & (start > 9) & (start < 13)",0.88199 +Departure Constants -- Midday 2 (13 to 15),escortTour==0,"(tour_type != ""escort"") & (start > 12) & (start < 16)",0.4111 +Departure Constants -- PM peak (16 to 18),escortTour==0,"(tour_type != ""escort"") & (start > 15) & (start < 19)",0 +Departure Constants -- Evening (19 to 21),escortTour==0,"(tour_type != ""escort"") & (start > 18) & (start < 22)",1.85648 +Departure Constants -- Late (22 and later),escortTour==0,"(tour_type != ""escort"") & (start > 21)",8.22888 +Arrival Constants -- Early (up to 6),escortTour==0,"(tour_type != ""escort"") & (end < 7)",0.05199 +Arrival Constants -- AM peak (7 to 9),escortTour==0,"(tour_type != ""escort"") & (end > 6) & (end < 10)",1.81482 +Arrival Constants -- Midday 1 (10 to 12),escortTour==0,"(tour_type != ""escort"") & (end > 9) & (end < 13)",0.00037 +Arrival Constants -- Midday 2 (13 to 14),escortTour==0,"(tour_type != ""escort"") & (end > 12) & (end < 15)",0.53212 +Arrival Constants -- PM peak 1 (15),escortTour==0,"(tour_type != ""escort"") & (end == 15)",0.62848 +Arrival Constants -- PM peak 2 (16),escortTour==0,"(tour_type != ""escort"") & (end == 16)",0.65052 +Arrival Constants -- PM peak 3 (17),escortTour==0,"(tour_type != ""escort"") & (end == 17)",0.40289 +Arrival Constants -- PM peak 4 (18),escortTour==0,"(tour_type != ""escort"") & (end == 18)",0.15421 +Arrival Constants -- Evening (19 to 21),escortTour==0,"(tour_type != ""escort"") & (end > 18) & (end < 22)",0 +Arrival Constants -- Late (22 and later),escortTour==0,"(tour_type != ""escort"") & (end > 21)",0.86667 +Duration Constants -- 0 to 1 hours,escortTour==0,"(tour_type != ""escort"") & (duration < 2)",0 +Duration Constants -- 2 to 3 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 1) & (duration < 4)",0.05139 +Duration Constants -- 4 to 5 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 3) & (duration < 6)",0.59395 +Duration Constants -- 6 to 7 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 5) & (duration < 8)",0.95116 +Duration Constants -- 8 to 10 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 7) & (duration < 11)",0.82811 +Duration Constants -- 11 to 13 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 10) & (duration < 14)",0.95564 +Duration Constants -- 14 to 18 hours,escortTour==0,"(tour_type != ""escort"") & (duration > 13) & (duration < 19)",1.04258 +Escort Tour Departure Constants -- Early (up to 5),escortTour==1,"(tour_type == ""escort"") & (start < 6)",1.74014 +Escort Tour Departure Constants -- AM peak 1 (6),escortTour==1,"(tour_type == ""escort"") & (start == 6)",1.11236 +Escort Tour Departure Constants -- AM peak 2 (7),escortTour==1,"(tour_type == ""escort"") & (start == 7)",0.69879 +Escort Tour Departure Constants -- AM peak 3 (8),escortTour==1,"(tour_type == ""escort"") & (start == 8)",1.19627 +Escort Tour Departure Constants -- AM peak 4 (9),escortTour==1,"(tour_type == ""escort"") & (start == 9)",0.22526 +Escort Tour Departure Constants -- Midday 1 (10 to 12),escortTour==1,"(tour_type == ""escort"") & (start > 9) & (start < 13)",0.02866 +Escort Tour Departure Constants -- Midday 2 (13 to 15),escortTour==1,"(tour_type == ""escort"") & (start > 12) & (start < 16)",0 +Escort Tour Departure Constants -- PM peak (16 to 18),escortTour==1,"(tour_type == ""escort"") & (start > 15) & (start < 19)",1.18014 +Escort Tour Departure Constants -- Evening (19 to 21),escortTour==1,"(tour_type == ""escort"") & (start > 18) & (start < 22)",3.94873 +Escort Tour Departure Constants -- Late (22 and later),escortTour==1,"(tour_type == ""escort"") & (start > 21)",8.22888 +Escort Tour Arrival Constants -- Early (up to 6),escortTour==1,"(tour_type == ""escort"") & (end < 7)",0 +Escort Tour Arrival Constants -- AM peak (7 to 9),escortTour==1,"(tour_type == ""escort"") & (end > 6) & (end < 10)",0 +Escort Tour Arrival Constants -- Midday 1 (10 to 12),escortTour==1,"(tour_type == ""escort"") & (end > 9) & (end < 13)",0 +Escort Tour Arrival Constants -- Midday 2 (13 to 14),escortTour==1,"(tour_type == ""escort"") & (end > 12) & (end < 15)",0 +Escort Tour Arrival Constants -- PM peak 1 (15),escortTour==1,"(tour_type == ""escort"") & (end == 15)",0 +Escort Tour Arrival Constants -- PM peak 2 (16),escortTour==1,"(tour_type == ""escort"") & (end == 16)",0 +Escort Tour Arrival Constants -- PM peak 3 (17),escortTour==1,"(tour_type == ""escort"") & (end == 17)",0 +Escort Tour Arrival Constants -- PM peak 4 (18),escortTour==1,"(tour_type == ""escort"") & (end == 18)",0 +Escort Tour Arrival Constants -- Evening (19 to 21),escortTour==1,"(tour_type == ""escort"") & (end > 18) & (end < 22)",0.53692 +Escort Tour Arrival Constants -- Late (22 and later),escortTour==1,"(tour_type == ""escort"") & (end > 21)",1.00829 +Escort Tour Duration Constants -- 0 to 1 hours,escortTour==1,"(tour_type == ""escort"") & (duration < 2)",0 +Escort Tour Duration Constants -- 2 to 3 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 1) & (duration < 4)",2.04201 +Escort Tour Duration Constants -- 4 to 5 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 3) & (duration < 6)",2.88029 +Escort Tour Duration Constants -- 6 to 7 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 5) & (duration < 8)",2.97353 +Escort Tour Duration Constants -- 8 to 10 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 7) & (duration < 11)",3.02021 +Escort Tour Duration Constants -- 11 to 13 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 10) & (duration < 14)",2.97436 +Escort Tour Duration Constants -- 14 to 18 hours,escortTour==1,"(tour_type == ""escort"") & (duration > 13) & (duration < 19)",2.50745 \ No newline at end of file diff --git a/example/configs/workplace_location.csv b/example/configs/workplace_location.csv index af7b3ce918..7958423b45 100644 --- a/example/configs/workplace_location.csv +++ b/example/configs/workplace_location.csv @@ -1 +1,17 @@ -Description,Expression,Alt "Distance, piecewise linear from 0 to 1 miles",@df.distance.clip(1),-0.8428 "Distance, piecewise linear from 1 to 2 miles","@(df.distance-1).clip(0,1)",-0.3104 "Distance, piecewise linear from 2 to 5 miles","@(df.distance-2).clip(0,3)",-0.3783 "Distance, piecewise linear from 5 to 15 miles","@(df.distance-5).clip(0,10)",-0.1285 "Distance, piecewise linear for 15+ miles",@(df.distance-15.0).clip(0),-0.0917 "Distance 0 to 5 mi, high and very high income",@(df.income_segment>=3)*df.distance.clip(upper=5),0.15 "Distance 5+ mi, high and very high income",@(df.income_segment>=3)*(df.distance-5).clip(0),0.02 "Size variable full-time worker, low income",@(df.income_segment==1)*df.size_low,1 "Size variable full-time worker, medium income",@(df.income_segment==2)*df.size_med,1 "Size variable full-time worker, high income",@(df.income_segment==3)*df.size_high,1 "Size variable full-time worker, very high income",@(df.income_segment==4)*df.size_veryhigh,1 "No attractions full-time worker, low income",@(df.income_segment==1)&(df.size_low==0),-999 "No attractions full-time worker, medium income",@(df.income_segment==2)&(df.size_med==0),-999 "No attractions full-time worker, high income",@(df.income_segment==3)&(df.size_high==0),-999 "No attractions full-time worker, very high income",@(df.income_segment==4)&(df.size_veryhigh==0),-999 Mode choice logsum,mcLogsum,0.3 \ No newline at end of file +Description,Expression,Alt +"Distance, piecewise linear from 0 to 1 miles",@df.distance.clip(1),-0.8428 +"Distance, piecewise linear from 1 to 2 miles","@(df.distance-1).clip(0,1)",-0.3104 +"Distance, piecewise linear from 2 to 5 miles","@(df.distance-2).clip(0,3)",-0.3783 +"Distance, piecewise linear from 5 to 15 miles","@(df.distance-5).clip(0,10)",-0.1285 +"Distance, piecewise linear for 15+ miles",@(df.distance-15.0).clip(0),-0.0917 +"Distance 0 to 5 mi, high and very high income",@(df.income_segment>=3)*df.distance.clip(upper=5),0.15 +"Distance 5+ mi, high and very high income",@(df.income_segment>=3)*(df.distance-5).clip(0),0.02 +"Size variable full-time worker, low income",@(df.income_segment==1)*df.size_low,1 +"Size variable full-time worker, medium income",@(df.income_segment==2)*df.size_med,1 +"Size variable full-time worker, high income",@(df.income_segment==3)*df.size_high,1 +"Size variable full-time worker, very high income",@(df.income_segment==4)*df.size_veryhigh,1 +"No attractions full-time worker, low income",@(df.income_segment==1)&(df.size_low==0),-999 +"No attractions full-time worker, medium income",@(df.income_segment==2)&(df.size_med==0),-999 +"No attractions full-time worker, high income",@(df.income_segment==3)&(df.size_high==0),-999 +"No attractions full-time worker, very high income",@(df.income_segment==4)&(df.size_veryhigh==0),-999 +Mode choice logsum,mode_choice_logsums,0.3 \ No newline at end of file diff --git a/example/configs/workplace_location_size_terms.csv b/example/configs/workplace_location_size_terms.csv deleted file mode 100644 index f9b7da433a..0000000000 --- a/example/configs/workplace_location_size_terms.csv +++ /dev/null @@ -1 +0,0 @@ -purpose,segment,TOTHH,RETEMPN,FPSEMPN,HEREMPN,OTHEMPN,AGREMPN,MWTEMPN,AGE0519,HSENROLL,COLLFTE,COLLPTE work,low,0,0.129,0.193,0.383,0.12,0.01,0.164,0,0,0,0 work,med,0,0.12,0.197,0.325,0.139,0.008,0.21,0,0,0,0 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,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 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,shopping,0,1,0,0,0,0,0,0,0,0,0 eatOut,eatOut,0,0.742,0,0.258,0,0,0,0,0,0,0 othMaint,othMaint,0,0.482,0,0.518,0,0,0,0,0,0,0 social,social,0,0.522,0,0.478,0,0,0,0,0,0,0 othDiscr,othDiscr,0.252,0.212,0,0.272,0.165,0,0,0,0.098,0,0 atwork,atwork,0,0.742,0,0.258,0,0,0,0,0,0,0 \ No newline at end of file diff --git a/notebooks/data_mover.ipynb b/example/data_mover.ipynb similarity index 93% rename from notebooks/data_mover.ipynb rename to example/data_mover.ipynb index 1c065abf11..e6329cec65 100644 --- a/notebooks/data_mover.ipynb +++ b/example/data_mover.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:afbc3e7040dd9e4a5b21433063f13a6a8abfcc04bcfc6574e7e43376c257cd33" + "signature": "sha256:07f23263339f1751ee4eb702d126692b9ed2785fe8640a8906eb0fb110d9e67a" }, "nbformat": 3, "nbformat_minor": 0, @@ -43,8 +43,10 @@ "col_map = {\n", " \"HHID\": \"household_id\",\n", " \"AGE\": \"age\",\n", + " \"SEX\": \"sex\",\n", " \"hworkers\": \"workers\",\n", - " \"HINC\": \"income\"\n", + " \"HINC\": \"income\",\n", + " \"AREATYPE\": \"area_type\"\n", "}" ], "language": "python", diff --git a/example/models.py b/example/models.py deleted file mode 100644 index 941d9973c9..0000000000 --- a/example/models.py +++ /dev/null @@ -1,142 +0,0 @@ -import urbansim.sim.simulation as sim -import os -from activitysim import activitysim as asim -import openmatrix as omx -from activitysim import skim -import numpy as np -import pandas as pd - - -@sim.table() -def auto_alts(): - return asim.identity_matrix(["cars%d" % i for i in range(5)]) - - -@sim.table() -def zones(): - # I grant this is a weird idiom but it helps to name the index - return pd.DataFrame({"TAZ": np.arange(1454)+1}).set_index("TAZ") - - -@sim.injectable() -def nonmotskm_omx(): - return omx.openFile('data/nonmotskm.omx') - - -@sim.injectable() -def distance_matrix(nonmotskm_omx): - return skim.Skim(nonmotskm_omx['DIST'], offset=-1) - - -@sim.injectable() -def auto_ownership_spec(): - f = os.path.join('configs', "auto_ownership_coeffs.csv") - return asim.read_model_spec(f).head(4*26) - - -@sim.injectable() -def workplace_location_spec(): - f = os.path.join('configs', "workplace_location.csv") - return asim.read_model_spec(f).head(15) - - -@sim.table() -def workplace_size_spec(): - f = os.path.join('configs', 'workplace_location_size_terms.csv') - return pd.read_csv(f) - - -@sim.table() -def workplace_size_terms(land_use, workplace_size_spec): - """ - This method takes the land use data and multiplies various columns of the - land use data by coefficients from the workplace_size_spec table in order - to yield a size term (a linear combination of land use variables) with - specified coefficients for different segments (like low, med, and high - income) - """ - land_use = land_use.to_frame() - df = workplace_size_spec.to_frame().query("purpose == 'work'") - df = df.drop("purpose", axis=1).set_index("segment") - new_df = {} - for index, row in df.iterrows(): - missing = row[~row.index.isin(land_use.columns)] - if len(missing) > 0: - print "WARNING: missing columns in land use\n", missing.index - row = row[row.index.isin(land_use.columns)] - sparse = land_use[list(row.index)] - new_df["size_"+index] = np.dot(sparse.as_matrix(), row.values) - new_df = pd.DataFrame(new_df, index=land_use.index) - return new_df - - -@sim.model() -def auto_ownership_simulate(households, - auto_alts, - auto_ownership_spec, - land_use, - accessibility): - - choosers = sim.merge_tables(households.name, tables=[households, - land_use, - accessibility]) - alternatives = auto_alts.to_frame() - - choices, model_design = \ - asim.simple_simulate(choosers, alternatives, auto_ownership_spec, - mult_by_alt_col=True) - - print "Choices:\n", choices.value_counts() - sim.add_column("households", "auto_ownership", choices) - - return model_design - - -@sim.model() -def workplace_location_simulate(persons, - households, - zones, - workplace_location_spec, - distance_matrix, - workplace_size_terms): - - choosers = sim.merge_tables(persons.name, tables=[persons, households]) - alternatives = zones.to_frame().join(workplace_size_terms.to_frame()) - - skims = { - "distance": distance_matrix - } - - choices, model_design = \ - asim.simple_simulate(choosers, - alternatives, - workplace_location_spec, - skims, - skim_join_name="TAZ", - mult_by_alt_col=False, - sample_size=50) - - print "Describe of hoices:\n", choices.describe() - sim.add_column("persons", "workplace_taz", choices) - - return model_design - - -@sim.column("land_use") -def total_households(land_use): - return land_use.local.TOTHH - - -@sim.column("land_use") -def total_employment(land_use): - return land_use.local.TOTEMP - - -@sim.column("land_use") -def total_acres(land_use): - return land_use.local.TOTACRE - - -@sim.column("land_use") -def county_id(land_use): - return land_use.local.COUNTY \ No newline at end of file diff --git a/example/simulation.ipynb b/example/simulation.ipynb new file mode 100644 index 0000000000..d31efb601e --- /dev/null +++ b/example/simulation.ipynb @@ -0,0 +1,957 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:6c45a354788860ab16482ccf9b5879eb72b95c7386ecef263a1fe44b08bb3352" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "import urbansim.sim.simulation as sim\n", + "from activitysim import defaults" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"workplace_location_simulate\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'workplace_location_simulate'\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['mode_choice_logsums']\n", + "Describe of choices:\n", + "count 2588.000000\n", + "mean 785.964451\n", + "std 422.797208\n", + "min 6.000000\n", + "25% 450.000000\n", + "50% 763.000000\n", + "75% 1199.000000\n", + "max 1443.000000\n", + "Name: TAZ, dtype: float64\n", + "Time to execute model 'workplace_location_simulate': 8.59s" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Total time to execute: 8.59s\n" + ] + } + ], + "prompt_number": 2 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "print sim.get_table(\"persons\").distance_to_work.describe()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "count 2588.000000\n", + "mean 41.955417\n", + "std 23.935534\n", + "min 0.290000\n", + "25% 23.492500\n", + "50% 39.580000\n", + "75% 56.205000\n", + "max 135.330000\n", + "dtype: float64\n" + ] + } + ], + "prompt_number": 3 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"auto_ownership_simulate\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'auto_ownership_simulate'\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(work_tour_auto_time_savings / (workers+1)) * cars1'\n", + " '(work_tour_auto_time_savings / (workers+1)) * cars2'\n", + " '(work_tour_auto_time_savings / (workers+1)) * cars3'\n", + " '(work_tour_auto_time_savings / (workers+1)) * cars4']\n", + "Choices:\n", + "2 383\n", + "1 328\n", + "3 140\n", + "0 104\n", + "4 45\n", + "dtype: int64\n", + "Time to execute model 'auto_ownership_simulate': 0.84s\n", + "Total time to execute: 0.84s\n" + ] + } + ], + "prompt_number": 4 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run(['mandatory_tour_frequency'])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'mandatory_tour_frequency'\n", + "865 persons run for mandatory tour model" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['((ptype == 6) & (distance_to_school < 3)) * school2'\n", + " '((ptype == 6) & (distance_to_work < 3 | distance_to_school < 3)) * work_and_school'\n", + " '((ptype == 2) & nonstudent_to_school) * school1'\n", + " '((ptype == 2) & nonstudent_to_school) * work_and_school'\n", + " '((ptype == 4) & nonstudent_to_school) * school1'\n", + " '((ptype == 5) & nonstudent_to_school) * school1'\n", + " '((ptype == 6) & (auto_ownership == 0)) * school2'\n", + " '((ptype == 6) & (auto_ownership == 0)) * work_and_school'\n", + " '(~(workplace_taz > -1)) * work1' '(~(workplace_taz > -1)) * work2'\n", + " '(~(workplace_taz > -1)) * work_and_school'\n", + " '(~(school_taz > -1)) * school1' '(~(school_taz > -1)) * school2'\n", + " '(~(school_taz > -1)) * work_and_school']\n", + "Choices:\n", + "school1 402\n", + "work1 268\n", + "work2 114\n", + "work_and_school 61\n", + "school2 20\n", + "dtype: int64\n", + "Time to execute model 'mandatory_tour_frequency': 3.60s\n", + "Total time to execute: 3.60s\n" + ] + } + ], + "prompt_number": 5 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.get_table(\"mandatory_tours\").tour_type.value_counts()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 9, + "text": [ + "work 557\n", + "school 503\n", + "dtype: int64" + ] + } + ], + "prompt_number": 9 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run(['non_mandatory_tour_frequency'])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'non_mandatory_tour_frequency'\n", + "1765 persons run for non-mandatory tour model" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Running segment 'driving' of size 49\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)'\n", + " '(car_sufficiency > 0) & (tot_tours == 1)'\n", + " '(car_sufficiency > 0) & (tot_tours == 2)'\n", + " '(car_sufficiency > 0) & (tot_tours == 3)'\n", + " '(car_sufficiency > 0) & (tot_tours == 4)'\n", + " '(car_sufficiency > 0) & (tot_tours > 4)']\n", + "Running segment 'full' of size 572\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Running segment 'nonwork' of size 364\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Running segment 'part' of size 136\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Running segment 'preschool' of size 146\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Running segment 'retired' of size 202\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Running segment 'school' of size 208\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)'\n", + " '(car_sufficiency > 0) & (tot_tours == 1)'\n", + " '(car_sufficiency > 0) & (tot_tours == 2)'\n", + " '(car_sufficiency > 0) & (tot_tours == 3)'\n", + " '(car_sufficiency > 0) & (tot_tours == 4)'\n", + " '(car_sufficiency > 0) & (tot_tours > 4)']\n", + "Running segment 'university' of size 88\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tot_tours == 0) & (num_mand == 0) & (num_joint_tours == 0)'\n", + " 'num_joint_tours*(tot_tours == 0)' 'num_joint_tours*(tot_tours == 1)'\n", + " 'num_joint_tours*(tot_tours == 2)' 'num_joint_tours*(tot_tours == 3)'\n", + " 'num_joint_tours*(tot_tours == 4)' 'num_joint_tours*(tot_tours > 4)'\n", + " 'num_shop_j' 'num_main_j' 'num_eat_j' 'num_visi_j' 'num_disc_j'\n", + " 'max_window*(tot_tours == 0)' 'max_window*(tot_tours == 1)'\n", + " 'max_window*(tot_tours == 2)' 'max_window*(tot_tours == 3)'\n", + " 'max_window*(tot_tours == 4)' 'max_window*(tot_tours > 4)']\n", + "Choices:\n", + "0 1762\n", + "16 2\n", + "32 1\n", + "dtype: int64\n", + "Time to execute model 'non_mandatory_tour_frequency': 11.87s\n", + "Total time to execute: 11.87s\n" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.get_table(\"non_mandatory_tours\").tour_type.value_counts()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 11, + "text": [ + "shopping 2\n", + "escort 1\n", + "dtype: int64" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"destination_choice\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'destination_choice'\n", + "Running segment 'shopping' of size 2" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Choices:\n", + "count 2.000000\n", + "mean 710.500000\n", + "std 137.885822\n", + "min 613.000000\n", + "25% 661.750000\n", + "50% 710.500000\n", + "75% 759.250000\n", + "max 808.000000\n", + "Name: TAZ, dtype: float64\n", + "Time to execute model 'destination_choice': 2.31s\n", + "Total time to execute: 2.31s\n" + ] + } + ], + "prompt_number": 12 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"mandatory_scheduling\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'mandatory_scheduling'\n", + "Running 1392 mandatory tour scheduling choices" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Running 808 non-mandatory #1 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(start < end_of_previous_tour) & (tour_num == 2)'\n", + " '(tour_num == 2) & (duration < 8)' '(tour_num == 2) * duration'\n", + " '(tour_num == 2) * start' 'home_is_rural & (end > 22)'\n", + " 'home_is_rural & (start < 6)' 'mode_choice_logsum']\n", + "Running 584 non-mandatory #2 tour choices" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(ptype == 3) * start' '(start < end_of_previous_tour) & (tour_num == 2)'\n", + " '(tour_num == 1) & (duration < 8)' '(tour_num == 1) * duration'\n", + " '(tour_num == 1) * start' 'home_is_rural & (end > 22)'\n", + " 'home_is_rural & (start < 6)' 'mode_choice_logsum']\n", + "Choices:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "count 1392.000000\n", + "mean 87.232759\n", + "std 58.336813\n", + "min 0.000000\n", + "25% 34.000000\n", + "50% 87.000000\n", + "75% 137.000000\n", + "max 189.000000\n", + "dtype: float64\n", + "Time to execute model 'mandatory_scheduling': 3.27s\n", + "Total time to execute: 3.27s\n" + ] + } + ], + "prompt_number": 9 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.run([\"non_mandatory_scheduling\"])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Running model 'non_mandatory_scheduling'\n", + "Running 1886 non-mandatory tour scheduling choices" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Running 528 non-mandatory #1 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['start < end_of_previous_tour']\n", + "Running 520 non-mandatory #2 tour choices" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['start < end_of_previous_tour']\n", + "Running 338 non-mandatory #3 tour choices" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['start < end_of_previous_tour']\n", + "Running 246 non-mandatory #4 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tour_type == \"shopping\") * duration' '(tour_type == \"shopping\") * start'\n", + " 'start < end_of_previous_tour']\n", + "Running 144 non-mandatory #5 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tour_type == \"shopping\") * duration' '(tour_type == \"shopping\") * start'\n", + " 'start < end_of_previous_tour']\n", + "Running 61 non-mandatory #6 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tour_type == \"shopping\") * duration' '(tour_type == \"shopping\") * start'\n", + " 'start < end_of_previous_tour']\n", + "Running 49 non-mandatory #7 tour choices\n", + "WARNING: Some columns have no variability:\n" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "['(tour_type == \"shopping\") * duration' '(tour_type == \"shopping\") * start'\n", + " 'start < end_of_previous_tour']\n", + "Choices:\n", + "count 1886.000000\n", + "mean 31.246023\n", + "std 33.805214\n", + "min 1.000000\n", + "25% 18.000000\n", + "50% 18.000000\n", + "75% 18.000000\n", + "max 188.000000\n", + "dtype: float64\n", + "Time to execute model 'non_mandatory_scheduling': 3.47s\n", + "Total time to execute: 3.47s\n" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.get_table(\"land_use\").to_frame().info()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Int64Index: 1454 entries, 1 to 1454\n", + "Data columns (total 49 columns):\n", + "DISTRICT 1454 non-null int64\n", + "SD 1454 non-null int64\n", + "COUNTY 1454 non-null int64\n", + "TOTHH 1454 non-null int64\n", + "HHPOP 1454 non-null int64\n", + "TOTPOP 1454 non-null int64\n", + "EMPRES 1454 non-null int64\n", + "SFDU 1454 non-null int64\n", + "MFDU 1454 non-null int64\n", + "HHINCQ1 1454 non-null int64\n", + "HHINCQ2 1454 non-null int64\n", + "HHINCQ3 1454 non-null int64\n", + "HHINCQ4 1454 non-null int64\n", + "TOTACRE 1454 non-null float64\n", + "RESACRE 1454 non-null int64\n", + "CIACRE 1454 non-null int64\n", + "SHPOP62P 1454 non-null float64\n", + "TOTEMP 1454 non-null int64\n", + "AGE0004 1454 non-null int64\n", + "AGE0519 1454 non-null int64\n", + "AGE2044 1454 non-null int64\n", + "AGE4564 1454 non-null int64\n", + "AGE65P 1454 non-null int64\n", + "RETEMPN 1454 non-null int64\n", + "FPSEMPN 1454 non-null int64\n", + "HEREMPN 1454 non-null int64\n", + "OTHEMPN 1454 non-null int64\n", + "AGREMPN 1454 non-null int64\n", + "MWTEMPN 1454 non-null int64\n", + "PRKCST 1454 non-null float64\n", + "OPRKCST 1454 non-null float64\n", + "area_type 1454 non-null int64\n", + "HSENROLL 1454 non-null float64\n", + "COLLFTE 1454 non-null float64\n", + "COLLPTE 1454 non-null float64\n", + "TOPOLOGY 1454 non-null int64\n", + "TERMINAL 1454 non-null float64\n", + "ZERO 1454 non-null int64\n", + "hhlds 1454 non-null int64\n", + "sftaz 1454 non-null int64\n", + "gqpop 1454 non-null int64\n", + "employment_density 1454 non-null float64\n", + "total_acres 1454 non-null float64\n", + "county_id 1454 non-null int64\n", + "density_index 1453 non-null float64\n", + "county_name 1454 non-null object\n", + "household_density 1454 non-null float64\n", + "total_households 1454 non-null int64\n", + "total_employment 1454 non-null int64\n", + "dtypes: float64(12), int64(36), object(1)\n", + "memory usage: 568.0 KB\n" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.get_table(\"households\").to_frame().info()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Int64Index: 1000 entries, 1605186 to 2171700\n", + "Data columns (total 75 columns):\n", + "TAZ 1000 non-null int64\n", + "SERIALNO 1000 non-null int64\n", + "PUMA5 1000 non-null int64\n", + "income 1000 non-null int64\n", + "PERSONS 1000 non-null int64\n", + "HHT 1000 non-null int64\n", + "UNITTYPE 1000 non-null int64\n", + "NOC 1000 non-null int64\n", + "BLDGSZ 1000 non-null int64\n", + "TENURE 1000 non-null int64\n", + "VEHICL 1000 non-null int64\n", + "hinccat1 1000 non-null int64\n", + "hinccat2 1000 non-null int64\n", + "hhagecat 1000 non-null int64\n", + "hsizecat 1000 non-null int64\n", + "hfamily 1000 non-null int64\n", + "hunittype 1000 non-null int64\n", + "hNOCcat 1000 non-null int64\n", + "hwrkrcat 1000 non-null int64\n", + "h0004 1000 non-null int64\n", + "h0511 1000 non-null int64\n", + "h1215 1000 non-null int64\n", + "h1617 1000 non-null int64\n", + "h1824 1000 non-null int64\n", + "h2534 1000 non-null int64\n", + "h3549 1000 non-null int64\n", + "h5064 1000 non-null int64\n", + "h6579 1000 non-null int64\n", + "h80up 1000 non-null int64\n", + "workers 1000 non-null int64\n", + "hwork_f 1000 non-null int64\n", + "hwork_p 1000 non-null int64\n", + "huniv 1000 non-null int64\n", + "hnwork 1000 non-null int64\n", + "hretire 1000 non-null int64\n", + "hpresch 1000 non-null int64\n", + "hschpred 1000 non-null int64\n", + "hschdriv 1000 non-null int64\n", + "htypdwel 1000 non-null int64\n", + "hownrent 1000 non-null int64\n", + "hadnwst 1000 non-null int64\n", + "hadwpst 1000 non-null int64\n", + "hadkids 1000 non-null int64\n", + "bucketBin 1000 non-null int64\n", + "originalPUMA 1000 non-null int64\n", + "hmultiunit 1000 non-null int64\n", + "has_preschool_kid 1000 non-null bool\n", + "family 1000 non-null bool\n", + "num_young_adults 1000 non-null float64\n", + "auto_ownership 1000 non-null int64\n", + "has_driving_kid 1000 non-null bool\n", + "has_non_worker 1000 non-null bool\n", + "has_preschool_kid_at_home 1000 non-null bool\n", + "home_taz 1000 non-null int64\n", + "has_retiree 1000 non-null bool\n", + "drivers 1000 non-null int64\n", + "num_under16_not_at_school 1000 non-null int64\n", + "has_full_time 1000 non-null bool\n", + "num_children 1000 non-null float64\n", + "car_sufficiency 1000 non-null int64\n", + "num_adolescents 1000 non-null float64\n", + "income_in_thousands 1000 non-null float64\n", + "has_school_kid 1000 non-null bool\n", + "num_college_age 1000 non-null float64\n", + "non_workers 1000 non-null int64\n", + "household_type 1000 non-null object\n", + "home_is_rural 1000 non-null bool\n", + "has_university 1000 non-null bool\n", + "non_family 1000 non-null bool\n", + "income_segment 1000 non-null category\n", + "has_part_time 1000 non-null bool\n", + "has_school_kid_at_home 1000 non-null bool\n", + "no_cars 1000 non-null bool\n", + "num_young_children 1000 non-null float64\n", + "home_is_urban 1000 non-null bool\n", + "dtypes: bool(15), category(1), float64(6), int64(52), object(1)\n", + "memory usage: 484.4 KB\n" + ] + } + ], + "prompt_number": 12 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "sim.get_table(\"persons\").to_frame().info()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Int64Index: 2569 entries, 553 to 7052832\n", + "Data columns (total 48 columns):\n", + "household_id 2569 non-null int64\n", + "age 2569 non-null int64\n", + "RELATE 2569 non-null int64\n", + "ESR 2569 non-null int64\n", + "GRADE 2569 non-null int64\n", + "PNUM 2569 non-null int64\n", + "PAUG 2569 non-null int64\n", + "DDP 2569 non-null int64\n", + "sex 2569 non-null int64\n", + "WEEKS 2569 non-null int64\n", + "HOURS 2569 non-null int64\n", + "MSP 2569 non-null int64\n", + "POVERTY 2569 non-null int64\n", + "EARNS 2569 non-null int64\n", + "pagecat 2569 non-null int64\n", + "pemploy 2569 non-null int64\n", + "pstudent 2569 non-null int64\n", + "ptype 2569 non-null int64\n", + "padkid 2569 non-null int64\n", + "student_cat 2569 non-null object\n", + "num_eat_j 2569 non-null int64\n", + "distance_to_school 2569 non-null float64\n", + "female 2569 non-null bool\n", + "non_mandatory_tour_frequency 1680 non-null float64\n", + "max_window 2569 non-null int64\n", + "employed_cat 2569 non-null object\n", + "student_is_employed 2569 non-null bool\n", + "distance_to_work 2569 non-null float64\n", + "cdap_activity 2569 non-null object\n", + "num_main_j 2569 non-null int64\n", + "num_joint_tours 2569 non-null int64\n", + "home_taz 2569 non-null int64\n", + "ptype_cat 2569 non-null object\n", + "is_student 2569 non-null bool\n", + "under16_not_at_school 2569 non-null bool\n", + "school_taz 2569 non-null int64\n", + "is_worker 2569 non-null bool\n", + "roundtrip_auto_time_to_school 2569 non-null float64\n", + "workplace_taz 2569 non-null int64\n", + "workplace_in_cbd 2569 non-null bool\n", + "nonstudent_to_school 2569 non-null bool\n", + "mandatory_tour_frequency 808 non-null object\n", + "num_shop_j 2569 non-null int64\n", + "num_mand 808 non-null float64\n", + "num_visi_j 2569 non-null int64\n", + "roundtrip_auto_time_to_work 2569 non-null float64\n", + "num_disc_j 2569 non-null int64\n", + "male 2569 non-null bool\n", + "dtypes: bool(8), float64(6), int64(29), object(5)\n", + "memory usage: 843.0 KB\n" + ] + } + ], + "prompt_number": 13 + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "The cell below is used to create small a dataset for testing" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import urbansim.sim.simulation as sim\n", + "from activitysim import activitysim as asim\n", + "from activitysim import defaults\n", + "import pandas as pd\n", + "old_store = sim.get_injectable('store')\n", + "print old_store\n", + "# subset of the whole store\n", + "new_store = pd.HDFStore('test.h5', 'w')\n", + "new_store[\"land_use/taz_data\"] = old_store[\"land_use/taz_data\"]\n", + "new_store[\"skims/accessibility\"] = old_store[\"skims/accessibility\"]\n", + "new_store[\"households\"] = asim.random_rows(old_store[\"households\"], 1000)\n", + "new_store[\"persons\"] = old_store[\"persons\"][\n", + " old_store[\"persons\"].household_id.isin(new_store[\"households\"].index)\n", + "]\n", + "print new_store\n", + "new_store.close()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "File path: ./data/mtc_asim.h5\n", + "/households frame (shape->[2732722,46])\n", + "/persons frame (shape->[7053334,19])\n", + "/land_use/taz_data frame (shape->[1454,41]) \n", + "/skims/accessibility frame (shape->[1454,10]) \n", + "\n", + "File path: test.h5\n", + "/households frame (shape->[1000,46])\n", + "/persons frame (shape->[2646,19])\n", + "/land_use/taz_data frame (shape->[1454,41])\n", + "/skims/accessibility frame (shape->[1454,10])" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n" + ] + } + ], + "prompt_number": 14 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 14 + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/notebooks/simulation.ipynb b/notebooks/simulation.ipynb deleted file mode 100644 index 1643e621dd..0000000000 --- a/notebooks/simulation.ipynb +++ /dev/null @@ -1,730 +0,0 @@ -{ - "metadata": { - "name": "", - "signature": "sha256:68dd59fb87c331bcb79d97a97557ee2ee411309bd3a85e58d6bee4b169b221df" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "%load_ext autoreload\n", - "%autoreload 2\n", - "if 'sim' not in globals():\n", - " import os; os.chdir('../example')\n", - "import urbansim.sim.simulation as sim\n", - "from activitysim.defaults import variables\n", - "import models" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sim.run([\"workplace_location_simulate\"])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Running model 'workplace_location_simulate'\n", - "Describe of hoices:\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "count 258078.000000\n", - "mean 718.510997\n", - "std 422.975764\n", - "min 1.000000\n", - "25% 352.000000\n", - "50% 719.000000\n", - "75% 1083.000000\n", - "max 1454.000000\n", - "Name: TAZ, dtype: float64\n", - "Time to execute model 'workplace_location_simulate': 35.33s" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "\n", - "Total time to execute: 35.34s\n" - ] - } - ], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sim.run([\"auto_ownership_simulate\"])" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "Running model 'auto_ownership_simulate'\n", - "Choices:\n" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "cars2 47959\n", - "cars3 38186\n", - "cars1 7528\n", - "cars4 5123\n", - "cars0 1204\n", - "dtype: int64\n", - "Time to execute model 'auto_ownership_simulate': 4.62s" - ] - }, - { - "output_type": "stream", - "stream": "stdout", - "text": [ - "\n", - "Total time to execute: 4.62s\n" - ] - } - ], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sim.get_table(\"land_use\").to_frame().describe()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
DISTRICTSDCOUNTYTOTHHHHPOPTOTPOPEMPRESSFDUMFDUHHINCQ1...hhldssftazgqpopemployment_densitytotal_acrescounty_iddensity_indexhousehold_densitytotal_householdstotal_employment
count 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000... 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 1453.000000 1454.000000 1454.000000 1454.000000
mean 14.908528 14.908528 3.835626 1793.688446 4816.408528 4917.978680 2168.684319 1122.798487 670.889959 508.134801... 1793.688446 727.500000 101.570151 9.596395 3146.071457 3.835626 2.279554 6.008186 1793.688446 2247.736589
std 8.701078 8.701078 2.040153 961.021405 2686.029808 2690.352928 1211.109335 854.895353 717.261660 378.753528... 961.021405 419.877958 393.886676 45.067313 16945.908840 2.040153 3.945717 8.565908 961.021405 3538.356220
min 1.000000 1.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000... 0.000000 1.000000 -1.000000 0.000000 13.000000 1.000000 0.000000 0.000000 0.000000 0.000000
25% 8.000000 8.000000 3.000000 1200.250000 3288.250000 3384.500000 1460.500000 602.000000 144.500000 257.000000... 1200.250000 364.250000 5.000000 0.877829 230.000000 3.000000 0.550232 1.910701 1200.250000 482.000000
50% 15.000000 15.000000 4.000000 1681.500000 4504.500000 4577.000000 2016.000000 1034.000000 460.000000 434.000000... 1681.500000 727.500000 18.000000 2.158701 397.000000 4.000000 1.289224 3.939122 1681.500000 1005.500000
75% 20.750000 20.750000 5.000000 2259.750000 6033.750000 6098.500000 2735.500000 1496.000000 907.750000 674.750000... 2259.750000 1090.750000 71.000000 5.492696 883.500000 5.000000 2.337577 6.693238 2259.750000 2215.750000
max 34.000000 34.000000 9.000000 12542.000000 39671.000000 40020.000000 16799.000000 12413.000000 4920.000000 3754.000000... 12542.000000 1454.000000 7810.000000 877.564767 372520.000000 9.000000 46.360371 90.891304 12542.000000 37950.000000
\n", - "

8 rows \u00d7 48 columns

\n", - "
" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "text": [ - " DISTRICT SD COUNTY TOTHH HHPOP \\\n", - "count 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 \n", - "mean 14.908528 14.908528 3.835626 1793.688446 4816.408528 \n", - "std 8.701078 8.701078 2.040153 961.021405 2686.029808 \n", - "min 1.000000 1.000000 1.000000 0.000000 0.000000 \n", - "25% 8.000000 8.000000 3.000000 1200.250000 3288.250000 \n", - "50% 15.000000 15.000000 4.000000 1681.500000 4504.500000 \n", - "75% 20.750000 20.750000 5.000000 2259.750000 6033.750000 \n", - "max 34.000000 34.000000 9.000000 12542.000000 39671.000000 \n", - "\n", - " TOTPOP EMPRES SFDU MFDU HHINCQ1 \\\n", - "count 1454.000000 1454.000000 1454.000000 1454.000000 1454.000000 \n", - "mean 4917.978680 2168.684319 1122.798487 670.889959 508.134801 \n", - "std 2690.352928 1211.109335 854.895353 717.261660 378.753528 \n", - "min 0.000000 0.000000 0.000000 0.000000 0.000000 \n", - "25% 3384.500000 1460.500000 602.000000 144.500000 257.000000 \n", - "50% 4577.000000 2016.000000 1034.000000 460.000000 434.000000 \n", - "75% 6098.500000 2735.500000 1496.000000 907.750000 674.750000 \n", - "max 40020.000000 16799.000000 12413.000000 4920.000000 3754.000000 \n", - "\n", - " ... hhlds sftaz gqpop \\\n", - "count ... 1454.000000 1454.000000 1454.000000 \n", - "mean ... 1793.688446 727.500000 101.570151 \n", - "std ... 961.021405 419.877958 393.886676 \n", - "min ... 0.000000 1.000000 -1.000000 \n", - "25% ... 1200.250000 364.250000 5.000000 \n", - "50% ... 1681.500000 727.500000 18.000000 \n", - "75% ... 2259.750000 1090.750000 71.000000 \n", - "max ... 12542.000000 1454.000000 7810.000000 \n", - "\n", - " employment_density total_acres county_id density_index \\\n", - "count 1454.000000 1454.000000 1454.000000 1453.000000 \n", - "mean 9.596395 3146.071457 3.835626 2.279554 \n", - "std 45.067313 16945.908840 2.040153 3.945717 \n", - "min 0.000000 13.000000 1.000000 0.000000 \n", - "25% 0.877829 230.000000 3.000000 0.550232 \n", - "50% 2.158701 397.000000 4.000000 1.289224 \n", - "75% 5.492696 883.500000 5.000000 2.337577 \n", - "max 877.564767 372520.000000 9.000000 46.360371 \n", - "\n", - " household_density total_households total_employment \n", - "count 1454.000000 1454.000000 1454.000000 \n", - "mean 6.008186 1793.688446 2247.736589 \n", - "std 8.565908 961.021405 3538.356220 \n", - "min 0.000000 0.000000 0.000000 \n", - "25% 1.910701 1200.250000 482.000000 \n", - "50% 3.939122 1681.500000 1005.500000 \n", - "75% 6.693238 2259.750000 2215.750000 \n", - "max 90.891304 12542.000000 37950.000000 \n", - "\n", - "[8 rows x 48 columns]" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "sim.get_table(\"households\").to_frame().describe()" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
TAZSERIALNOPUMA5incomePERSONSHHTUNITTYPENOCBLDGSZTENURE...bucketBinoriginalPUMAhmultiunitnum_young_adultsdriversnum_childrennum_adolescentsincome_in_thousandsnum_young_childrennum_college_age
count 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000... 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000
mean 752.439040 4924260.422350 2168.287950 77684.096720 2.580780 2.642540 0.077640 0.468280 3.529460 1.892780... 4.484880 2168.287950 0.401800 0.394180 2.063810 0.357290 0.060680 77.684097 0.159680 0.226650
std 430.258155 2863687.886756 516.271349 81341.474187 1.606362 2.066835 0.367387 0.913982 2.517375 1.010353... 2.871932 516.271349 0.490264 0.728922 1.122662 0.760368 0.260074 81.341474 0.462498 0.589748
min 1.000000 496.000000 1000.000000 -20000.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000... 0.000000 1000.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -20.000000 0.000000 0.000000
25% 374.000000 2456274.500000 2104.000000 26500.000000 1.000000 1.000000 0.000000 0.000000 2.000000 1.000000... 2.000000 2104.000000 0.000000 0.000000 1.000000 0.000000 0.000000 26.500000 0.000000 0.000000
50% 764.000000 4895910.500000 2303.000000 58000.000000 2.000000 1.000000 0.000000 0.000000 2.000000 2.000000... 4.000000 2303.000000 0.000000 0.000000 2.000000 0.000000 0.000000 58.000000 0.000000 0.000000
75% 1144.000000 7357629.750000 2410.000000 100000.000000 4.000000 4.000000 0.000000 1.000000 5.000000 3.000000... 7.000000 2410.000000 1.000000 1.000000 2.000000 0.000000 0.000000 100.000000 0.000000 0.000000
max 1454.000000 9999811.000000 2714.000000 1237000.000000 25.000000 7.000000 2.000000 10.000000 10.000000 4.000000... 9.000000 2714.000000 1.000000 9.000000 25.000000 8.000000 5.000000 1237.000000 8.000000 24.000000
\n", - "

8 rows \u00d7 53 columns

\n", - "
" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - " TAZ SERIALNO PUMA5 income \\\n", - "count 100000.000000 100000.000000 100000.000000 100000.000000 \n", - "mean 752.439040 4924260.422350 2168.287950 77684.096720 \n", - "std 430.258155 2863687.886756 516.271349 81341.474187 \n", - "min 1.000000 496.000000 1000.000000 -20000.000000 \n", - "25% 374.000000 2456274.500000 2104.000000 26500.000000 \n", - "50% 764.000000 4895910.500000 2303.000000 58000.000000 \n", - "75% 1144.000000 7357629.750000 2410.000000 100000.000000 \n", - "max 1454.000000 9999811.000000 2714.000000 1237000.000000 \n", - "\n", - " PERSONS HHT UNITTYPE NOC \\\n", - "count 100000.000000 100000.000000 100000.000000 100000.000000 \n", - "mean 2.580780 2.642540 0.077640 0.468280 \n", - "std 1.606362 2.066835 0.367387 0.913982 \n", - "min 1.000000 0.000000 0.000000 0.000000 \n", - "25% 1.000000 1.000000 0.000000 0.000000 \n", - "50% 2.000000 1.000000 0.000000 0.000000 \n", - "75% 4.000000 4.000000 0.000000 1.000000 \n", - "max 25.000000 7.000000 2.000000 10.000000 \n", - "\n", - " BLDGSZ TENURE ... bucketBin \\\n", - "count 100000.000000 100000.000000 ... 100000.000000 \n", - "mean 3.529460 1.892780 ... 4.484880 \n", - "std 2.517375 1.010353 ... 2.871932 \n", - "min 0.000000 0.000000 ... 0.000000 \n", - "25% 2.000000 1.000000 ... 2.000000 \n", - "50% 2.000000 2.000000 ... 4.000000 \n", - "75% 5.000000 3.000000 ... 7.000000 \n", - "max 10.000000 4.000000 ... 9.000000 \n", - "\n", - " originalPUMA hmultiunit num_young_adults drivers \\\n", - "count 100000.000000 100000.000000 100000.000000 100000.000000 \n", - "mean 2168.287950 0.401800 0.394180 2.063810 \n", - "std 516.271349 0.490264 0.728922 1.122662 \n", - "min 1000.000000 0.000000 0.000000 0.000000 \n", - "25% 2104.000000 0.000000 0.000000 1.000000 \n", - "50% 2303.000000 0.000000 0.000000 2.000000 \n", - "75% 2410.000000 1.000000 1.000000 2.000000 \n", - "max 2714.000000 1.000000 9.000000 25.000000 \n", - "\n", - " num_children num_adolescents income_in_thousands \\\n", - "count 100000.000000 100000.000000 100000.000000 \n", - "mean 0.357290 0.060680 77.684097 \n", - "std 0.760368 0.260074 81.341474 \n", - "min 0.000000 0.000000 -20.000000 \n", - "25% 0.000000 0.000000 26.500000 \n", - "50% 0.000000 0.000000 58.000000 \n", - "75% 0.000000 0.000000 100.000000 \n", - "max 8.000000 5.000000 1237.000000 \n", - "\n", - " num_young_children num_college_age \n", - "count 100000.000000 100000.000000 \n", - "mean 0.159680 0.226650 \n", - "std 0.462498 0.589748 \n", - "min 0.000000 0.000000 \n", - "25% 0.000000 0.000000 \n", - "50% 0.000000 0.000000 \n", - "75% 0.000000 0.000000 \n", - "max 8.000000 24.000000 \n", - "\n", - "[8 rows x 53 columns]" - ] - } - ], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - } - ], - "metadata": {} - } - ] -} \ No newline at end of file