Below is one possible solution to Practice Exercise B with comments to explain what is going on. If you find a more efficient way to code a solution, please share it through the discussion forums.
# This script determines the percentage of cities with two park # and ride facilities import arcpy arcpy.env.overwriteOutput = True arcpy.env.workspace = r"C:\PSU\geog485\L3\PracticeExerciseB\Washington.gdb" cityBoundariesFC = "CityBoundaries" parkAndRideFC = "ParkAndRide" parkAndRideField = "HasTwoParkAndRides" # Name of column for storing the Park & Ride information cityIDStringField = "CI_FIPS" # Name of column with city IDs citiesWithTwoParkAndRides = 0 # Used for counting cities with at least two P & R facilities numCities = 0 # Used for counting cities in total # Make an update cursor and loop through each city with arcpy.da.UpdateCursor(cityBoundariesFC, (cityIDStringField, parkAndRideField)) as cityRows: for city in cityRows: # Create a query string for the current city cityIDString = city[0] whereClause = cityIDStringField + " = '" + cityIDString + "'" print("Processing city " + cityIDString) # Make a feature layer of just the current city polygon currentCityLayer = arcpy.SelectLayerByAttribute_management(cityBoundariesFC, "NEW_SELECTION", whereClause) try: # Narrow down the park and ride layer by selecting only the park and rides in the current city selectedParkAndRideLayer = arcpy.SelectLayerByLocation_management(parkAndRideFC, "CONTAINED_BY", currentCityLayer) # Count the number of park and ride facilities selected numSelectedParkAndRide = int(selectedParkAndRideLayer[2]) # If more than two park and ride facilities found, update the row to TRUE if numSelectedParkAndRide >= 2: city[1] = "TRUE" # Don't forget to call updateRow cityRows.updateRow(city) # Add 1 to your tally of cities with two park and rides citiesWithTwoParkAndRides += 1 numCities += 1 except: print("Problem determining number of ParkAndRides in " + cityIDString) finally: # Clean up feature layers arcpy.Delete_management(selectedParkAndRideLayer) arcpy.Delete_management(currentCityLayer) del city, cityRows # Calculate and report the number of cities with two park and rides if numCities != 0: percentCitiesWithParkAndRide = (citiesWithTwoParkAndRides / numCities) * 100 print (str(round(percentCitiesWithParkAndRide,1)) + " percent of cities have two park and rides.") else: print ("Error with input dataset. No cities found.")
The video below offers some line-by-line commentary on the structure of the above solution:
Video: Solution to Lesson 3, Practice Exercise B (8:57)
Here is a different solution to Practice Exercise B, which uses the alternate syntax discussed in the lesson.
# This script determines the percentage of cities with two park # and ride facilities import arcpy arcpy.env.overwriteOutput = True arcpy.env.workspace = r"C:\PSU\geog485\L3\PracticeExerciseB\Washington.gdb" cityBoundariesFC = "CityBoundaries" parkAndRideFC = "ParkAndRide" parkAndRideField = "HasTwoParkAndRides" # Name of column for storing the Park & Ride information cityIDStringField = "CI_FIPS" # Name of column with city IDs citiesWithTwoParkAndRides = 0 # Used for counting cities with at least two P & R facilities numCities = 0 # Used for counting cities in total # Make a feature layer of all the park and ride facilities arcpy.MakeFeatureLayer_management(parkAndRideFC, "ParkAndRideLayer") # Make an update cursor and loop through each city with arcpy.da.UpdateCursor(cityBoundariesFC, (cityIDStringField, parkAndRideField)) as cityRows: for city in cityRows: # Create a query string for the current city cityIDString = city[0] whereClause = cityIDStringField + " = '" + cityIDString + "'" print("Processing city " + cityIDString) # Make a feature layer of just the current city polygon arcpy.MakeFeatureLayer_management(cityBoundariesFC, "CurrentCityLayer", whereClause) try: # Narrow down the park and ride layer by selecting only the park and rides # in the current city arcpy.SelectLayerByLocation_management("ParkAndRideLayer", "CONTAINED_BY", "CurrentCityLayer") # Count the number of park and ride facilities selected selectedParkAndRideCount = arcpy.GetCount_management("ParkAndRideLayer") numSelectedParkAndRide = int(selectedParkAndRideCount[0]) # If more than two park and ride facilities found, update the row to TRUE if numSelectedParkAndRide >= 2: city[1] = "TRUE" # Don't forget to call updateRow cityRows.updateRow(city) # Add 1 to your tally of cities with two park and rides citiesWithTwoParkAndRides += 1 numCities += 1 except: print("Problem determining number of ParkAndRides in " + cityIDString) finally: # Clean up feature layer arcpy.Delete_management("CurrentCityLayer") # Clean up feature layer arcpy.Delete_management("ParkAndRideLayer") del city, cityRows # Calculate and report the number of cities with two park and rides if numCities != 0: percentCitiesWithParkAndRide = (citiesWithTwoParkAndRides / numCities) * 100 print (str(round(percentCitiesWithParkAndRide,1)) + " percent of cities have two park and rides.") else: print ("Error with input dataset. No cities found.")
The video below offers some line-by-line commentary on the structure of the above solution:
Video: Alternate Solution to Lesson 3, Practice Exercise B (2:10)
Testing these scripts on a ~2-year-old Dell laptop running Windows 10 with 16GB of RAM yielded some very different results. In 5 trials of both scripts, the first one needed an average of 240 seconds to complete. The second one (using the older syntax) needed only 83 seconds. This may seem counterintuitive, though it's interesting to note that the newer syntax was the faster performing version of the scripts for the other 3 exercises (times shown in seconds):
Exercise | Old | New |
A | 0.99 | 0.45 |
B | 83.67 | 240.33 |
C | 1.78 | 0.85 |
D | 1.46 | 0.92 |
You can check the timing of the scripts on your machine by adding the following lines just after the import arcpy statement:
import time process_start_time = time.time()
and this line at the end of the script:
print ("--- %s seconds ---" % (time.time() - process_start_time))
If you're interested in learning more about testing your script's performance along with methods for determining how long it takes to execute various parts of your script (e.g., to explore why there is such a difference in performance between the two Exercise B solutions), you should consider enrolling in our GEOG 489 class.