class: center, middle, inverse, title-slide # Oh, The Places You’ll Rent: Suitability Analysis for Incoming Students ## GEOG625 Final Project ### David Ranzolin ### May 19, 2021 --- <style type="text/css"> .remark-code, .remark-inline-code { font-family: 'Source Code Pro', 'Lucida Console', Monaco, monospace; font-size: 60%; } </style> <style type="text/css"> .title-slide h3:nth-of-type(9) { position: absolute; top: 0; } </style> # What is a Suitability Analysis? > *Suitability analysis is a geographic, or GIS-based process used to determine the appropriateness of a given area for a particular use...Suitability is determined through systematic, multi-factor analysis of the different aspects of the terrain. Model inputs include a variety of physical, cultural, and economic factors.* .pull-right[ \- [Per Wikipedia](https://en.wikipedia.org/wiki/Suitability_analysis) ] --- # Criteria for Incoming Students - Proximity to San Francisco State Campus -- - Proximity to public transit (BART, CalTrain, etc.) -- - Maximum Rent (1br, 2019 census tract estimates) -- - Elevation -- - ? --- # Level of Abstraction? <center> <img src="images/tweet.png" style="width:555px;height:455px;"> </center> --- # Initial Geoprocessing .panelset[ .panel[.panel-name[sfsu.py] .pull-left[ ```python import arcpy import sys, os from arcpy import env from arcpy import management as DM env.workspace = os.path.dirname(sys.argv[0]) arcpy.env.overwriteOutput = True outPoint = "sfsu" outPointPath = os.path.join("projdata.gdb", outPoint) if arcpy.Exists(outPointPath): DM.Delete(outPointPath) shp_out = DM.CreateFeatureclass("projdata.gdb", outPoint, "POINT", spatial_reference=4326) cur = arcpy.da.InsertCursor(shp_out, ["SHAPE@XY"]) sfsu = (-122.4799, 37.7241) cur.insertRow([sfsu]) del cur outPointPathProjected = os.path.join("projdata.gdb", "sfsuProjected") outSR = arcpy.SpatialReference(26943) DM.Project(outPointPath, outPointPathProjected, outSR) ``` ] .pull-right[ <img src="images/sfsu.png" style="height:400px;'"> ] ] .panel[.panel-name[rentTracts.R] .pull-left[ ```r ba_counties <- c("Alameda", "San Francisco", "Santa Clara", "San Mateo", "Contra Costa", "Marin", "Solano") get_ba_rent_tracts <- purrr::partial( tidycensus::get_acs, state = "CA", geography = "tract", variables = "B25031_003", geometry = TRUE ) ba_counties %>% purrr::map_dfr(~{ get_ba_rent_tracts(county = .x) }) %>% sf::st_write("ba_1br_rent_estimates.shp") ``` ] .pull-right[ <img src="images/bamaprent.png"> ] ] .panel[.panel-name[BA_TransitStops.shp] <center> <img src="images/batransit.png" style="width:525px;height:425px;"> </center> ] .panel[.panel-name[BAdem90.tif] <center> <img src="images/dem.png" style="width:525px;height:425px;"> </center> ] .panel[.panel-name[init_gdb.py] ```python import arcpy import sys, os from arcpy import env from arcpy import management as DM env.workspace = os.path.dirname(sys.argv[0]) projgdb = "projdata.gdb" if arcpy.Exists(projgdb): DM.Delete(projgdb) DM.CreateFileGDB(env.workspace, projgdb) print("Created projdata.gdb...\n") to_transfer = ["sfsuProjected", "BAdem90.tif", "BA_TransitStops.shp", "ba_1br_rent_estimates.shp"] for file in to_transfer: DM.TransferFiles(file, projgdb) ``` ] ] --- # The Toolbox: Rent Suitability .panelset[ .panel[.panel-name[Parameters] .pull-left[ ```python # .... rentMax = arcpy.Parameter( displayName = "Max Rent", name = "rentMax", datatype = "Double", parameterType = "Required", direction = "Input" ) transitPoints = arcpy.Parameter( displayName = "Transit Points", name = "transitPoints", datatype = "Feature Class", parameterType = "Optional", direction = "Input" ) transitSQL = arcpy.Parameter( displayName = "Subset Transit Feature Class w/SQL", name = "transitSQL", datatype = "SQL Expression", parameterType = "Optional", direction = "Input" ) #.... ``` ] .pull-right[ <img src="images/toolgui.png" style="height:500px;width:305px;"> ] ] .panel[.panel-name[Rent] ```python rentTractsSelectionSQL = '"estimate" <= {}'.format(rentMax) rentTractsSelection = DM.SelectLayerByAttribute(rentTracts, 'SUBSET_SELECTION', rentTractsSelectionSQL) ``` <center> <img src="images/rentSelection.png" style="height:350px;width:425px;"> </center> ] .panel[.panel-name[Transit] ```python transitSelection = DM.SelectLayerByAttribute(transitPoints, 'SUBSET_SELECTION', transitSQL) ``` <center> <img src="images/transitSelection.png" style="height:350px;width:425px;"> </center> ] .panel[.panel-name[Proximity] ```python def EucDistanceAndJoinZonalToTracts(self, location, zones, fieldName): """Run the Euclidian Distance, ZonalStatisticsAsTable, and Join Field tools""" outEucDistance = EucDistance(location) zonalTable = "zonalTable.dbf" outZonalDistanceFromLocation = ZonalStatisticsAsTable(zones, "OBJECTID", outEucDistance, zonalTable, "NODATA", "MEAN") tractsWithZonalDistance = DM.JoinField(zones, "OBJECTID", outZonalDistanceFromLocation, "OBJECTID", ["MEAN"]) DM.AlterField(tractsWithZonalDistance, "MEAN", fieldName, fieldName) DM.Delete(zonalTable) return tractsWithZonalDistance ``` <center> <img src="images/distRaster.png" style="height:220px;width:290px"> </center> ] .panel[.panel-name[Cleanup] ```python #..... with arcpy.da.UpdateCursor(tractsWithDistance2, ["MilesFromLoc", "MilesFromTransit"]) as cur: for row in cur: if row[0] is not None: row[0] = row[0]/1609 if row[1] is not None: row[1] = row[1]/1609 cur.updateRow(row) del cur outFieldNames = [f.name for f in arcpy.ListFields(tractsWithDistance2)] for f in outFieldNames: if "MEAN_" in f: DM.DeleteField(tractsWithDistance2, f) outSelectionSQL = (f'"estimate" <= {rentMax}' f'AND "MilesFromLoc" <= {milesFromLocation}' f'AND "MilesFromTransit" <= {milesFromTransit}') rentTractsSelection = DM.SelectLayerByAttribute(tractsWithDistance2, 'SUBSET_SELECTION', outSelectionSQL) DM.CopyFeatures(rentTractsSelection, outputPath) arcpy.AddMessage("Done!") ``` ] ] --- # Map Parameters: 30 Miles from Campus; $1,100 Max Rent (1br); 5 Miles from a BART Station
--- class: center, middle # Fin