def price_vars(net): nodes2 = networks.from_yaml(net, "price_vars.yaml") nodes2 = nodes2.fillna(0) print(nodes2.describe()) nodes = sim.get_table('nodes') nodes = nodes.to_frame().join(nodes2) sim.add_table("nodes", nodes)
def simple_transition(tbl, rate, location_fname): """ Run a simple growth rate transition model on the table passed in Parameters ---------- tbl : DataFrameWrapper Table to be transitioned rate : float Growth rate location_fname : str The field name in the resulting dataframe to set to -1 (to unplace new agents) Returns ------- Nothing """ transition = GrowthRateTransition(rate) df = tbl.to_frame(tbl.local_columns) print("%d agents before transition" % len(df.index)) df, added, copied, removed = transition.transition(df, None) print("%d agents after transition" % len(df.index)) df.loc[added, location_fname] = -1 sim.add_table(tbl.name, df)
def full_transition(agents, agent_controls, year, settings, location_fname): """ Run a transition model based on control totals specified in the usual UrbanSim way Parameters ---------- agents : DataFrameWrapper Table to be transitioned agent_controls : DataFrameWrapper Table of control totals year : int The year, which will index into the controls settings : dict Contains the configuration for the transition model - is specified down to the yaml level with a "total_column" which specifies the control total and an "add_columns" param which specified which columns to add when calling to_frame (should be a list of the columns needed to do the transition location_fname : str The field name in the resulting dataframe to set to -1 (to unplace new agents) Returns ------- Nothing """ ct = agent_controls.to_frame() hh = agents.to_frame(agents.local_columns + settings['add_columns']) print("Total agents before transition: {}".format(len(hh))) tran = transition.TabularTotalsTransition(ct, settings['total_column']) model = transition.TransitionModel(tran) new, added_hh_idx, new_linked = model.transition(hh, year) new.loc[added_hh_idx, location_fname] = -1 print("Total agents after transition: {}".format(len(new))) sim.add_table(agents.name, new)
def neighborhood_vars(net): nodes = networks.from_yaml(net, "neighborhood_vars.yaml") nodes = nodes.fillna(0) print(nodes.describe()) sim.add_table("nodes", nodes)
def run_feasibility(parcels, parcel_price_callback, parcel_use_allowed_callback, residential_to_yearly=True, parcel_filter=None, only_built=True, forms_to_test=None, config=None, pass_through=[]): """ Execute development feasibility on all parcels Parameters ---------- parcels : DataFrame Wrapper The data frame wrapper for the parcel data parcel_price_callback : function A callback which takes each use of the pro forma and returns a series with index as parcel_id and value as yearly_rent parcel_use_allowed_callback : function A callback which takes each form of the pro forma and returns a series with index as parcel_id and value and boolean whether the form is allowed on the parcel residential_to_yearly : boolean (default true) Whether to use the cap rate to convert the residential price from total sales price per sqft to rent per sqft parcel_filter : string A filter to apply to the parcels data frame to remove parcels from consideration - is typically used to remove parcels with buildings older than a certain date for historical preservation, but is generally useful only_built : boolean Only return those buildings that are profitable - only those buildings that "will be built" forms_to_test : list of strings (optional) Pass the list of the names of forms to test for feasibility - if set to None will use all the forms available in ProFormaConfig config : SqFtProFormaConfig configuration object. Optional. Defaults to None pass_through : list of strings Will be passed to the feasibility lookup function - is used to pass variables from the parcel dataframe to the output dataframe, usually for debugging Returns ------- Adds a table called feasibility to the sim object (returns nothing) """ pf = sqftproforma.SqFtProForma(config) if config \ else sqftproforma.SqFtProForma() df = parcels.to_frame() if parcel_filter: df = df.query(parcel_filter) # add prices for each use for use in pf.config.uses: # assume we can get the 80th percentile price for new development df[use] = parcel_price_callback(use) # convert from cost to yearly rent if residential_to_yearly: df["residential"] *= pf.config.cap_rate print("Describe of the yearly rent by use") print(df[pf.config.uses].describe()) d = {} forms = forms_to_test or pf.config.forms for form in forms: print("Computing feasibility for form %s" % form) allowed = parcel_use_allowed_callback(form).loc[df.index] d[form] = pf.lookup(form, df[allowed], only_built=only_built, pass_through=pass_through) if residential_to_yearly and "residential" in pass_through: d[form]["residential"] /= pf.config.cap_rate far_predictions = pd.concat(d.values(), keys=d.keys(), axis=1) far_predictions['residential'].max_profit = far_predictions['residential'].max_profit / np.power(far_predictions['residential'].max_profit_far*far_predictions['residential'].shape_area,1) far_predictions['industrial'].max_profit = far_predictions['industrial'].max_profit / np.power(far_predictions['industrial'].max_profit_far*far_predictions['industrial'].shape_area,1) far_predictions['retail'].max_profit = far_predictions['retail'].max_profit / np.power(far_predictions['retail'].max_profit_far*far_predictions['retail'].shape_area,1) far_predictions['office'].max_profit = far_predictions['office'].max_profit / np.power(far_predictions['office'].max_profit_far*far_predictions['office'].shape_area,1) #far_predictions['residential'].max_profit = np.divide(far_predictions['residential'].max_profit,far_predictions['residential'].max_dua) #far_predictions['residential'].max_profit[far_predictions['residential'].max_profit==-np.inf] = np.nan sim.add_table("feasibility", far_predictions)
def run_developer(forms, agents, buildings, buildings_all, supply_fname, parcel_size, ave_unit_size, total_units, feasibility, year=None, target_vacancy=.1, form_to_btype_callback=None, add_more_columns_callback=None, max_parcel_size=34647265, residential=True, bldg_sqft_per_job=400.0, min_unit_size=400, remove_developed_buildings=True, unplace_agents=['households', 'jobs']): """ Run the developer model to pick and build buildings Parameters ---------- forms : string or list of strings Passed directly dev.pick agents : DataFrame Wrapper Used to compute the current demand for units/floorspace in the area buildings : DataFrame Wrapper Used to compute the current supply of units/floorspace in the area buildings_all: Buildings for the entire region, used to write back to buildings table supply_fname : string Identifies the column in buildings which indicates the supply of units/floorspace parcel_size : Series Passed directly to dev.pick ave_unit_size : Series Passed directly to dev.pick - average residential unit size total_units : Series Passed directly to dev.pick - total current residential_units / job_spaces feasibility : DataFrame Wrapper The output from feasibility above (the table called 'feasibility') year : int The year of the simulation - will be assigned to 'year_built' on the new buildings target_vacancy : float The target vacancy rate - used to determine how much to build form_to_btype_callback : function Will be used to convert the 'forms' in the pro forma to 'building_type_id' in the larger model add_more_columns_callback : function Takes a dataframe and returns a dataframe - is used to make custom modifications to the new buildings that get added max_parcel_size : float Passed directly to dev.pick - max parcel size to consider min_unit_size : float Passed directly to dev.pick - min unit size that is valid residential : boolean Passed directly to dev.pick - switches between adding/computing residential_units and job_spaces bldg_sqft_per_job : float Passed directly to dev.pick - specified the multiplier between floor spaces and job spaces for this form (does not vary by parcel as ave_unit_size does) remove_redeveloped_buildings : optional, boolean (default True) Remove all buildings on the parcels which are being developed on unplace_agents : optional : list of strings (default ['households', 'jobs']) For all tables in the list, will look for field building_id and set it to -1 for buildings which are removed - only executed if remove_developed_buildings is true Returns ------- Writes the result back to the buildings table and returns the new buildings with available debugging information on each new building """ dev = developer.Developer(feasibility.to_frame()) #dev = WFRCDeveloper.WFRCDeveloper(feasibility.to_frame()) target_units = dev.\ compute_units_to_build(len(agents), buildings[supply_fname].sum(), target_vacancy) print("{:,} feasible buildings before running developer".format( len(dev.feasibility))) new_buildings = dev.pick(forms, target_units, parcel_size, ave_unit_size, total_units, max_parcel_size=max_parcel_size, min_unit_size=min_unit_size, drop_after_build=True, residential=residential, bldg_sqft_per_job=bldg_sqft_per_job) sim.add_table("feasibility", dev.feasibility) year = sim.get_injectable('year') if new_buildings is None: return if len(new_buildings) == 0: return new_buildings if not isinstance(forms, list): # form gets set only if forms is a list new_buildings["form"] = forms if form_to_btype_callback is not None: new_buildings["building_type_id"] = new_buildings.\ apply(form_to_btype_callback, axis=1) new_buildings["stories"] = new_buildings.stories.apply(np.ceil) new_buildings["note"] = "simulated" ret_buildings = new_buildings if add_more_columns_callback is not None: new_buildings = add_more_columns_callback(new_buildings) if year is not None: new_buildings["year_built"] = year print("Adding {:,} buildings with {:,} {}". format(len(new_buildings), int(new_buildings[supply_fname].sum()), supply_fname)) print("{:,} feasible buildings after running developer".format( len(dev.feasibility))) old_buildings = buildings.to_frame(buildings.local_columns) old_buildings_all = buildings_all.to_frame(buildings.local_columns) new_buildings = new_buildings[buildings.local_columns] if remove_developed_buildings: redev_buildings = old_buildings.parcel_id.isin(new_buildings.parcel_id) redev_buildings_all = old_buildings_all.parcel_id.isin(new_buildings.parcel_id) l = len(old_buildings) drop_buildings = old_buildings[redev_buildings] drop_buildings_all = old_buildings_all[redev_buildings_all] old_buildings = old_buildings[np.logical_not(redev_buildings)] old_buildings_all = old_buildings_all[np.logical_not(redev_buildings_all)] l2 = len(old_buildings) print("before dropped l:" + str(l)) print("after dropped l2: " + str(l2)) #print redev_buildings #print drop_buildings if l2-l > 0: print("Dropped {} buildings because they were redeveloped". format(l2 - l)) for tbl in unplace_agents: agents = sim.get_table(tbl) agents = agents.to_frame(agents.local_columns) #displaced_agents = agents.building_id.isin(drop_buildings.index) displaced_agents = agents.building_id.isin(drop_buildings_all.index) print("Unplaced {} before: {}".format(tbl, len(agents.query( "building_id == -1")))) agents.building_id[displaced_agents] = -1 print("Unplaced {} after: {}".format(tbl, len(agents.query( "building_id == -1")))) sim.add_table(tbl, agents) all_buildings = dev.merge(old_buildings_all, new_buildings) sim.add_table("buildings", all_buildings) return ret_buildings