One of the most important parts of performing network analysis with the arcpy.nax module is accessing the analysis outputs. When you solve your analysis using the solve method, a solver result object is returned, and this result object has several methods that can be used to retrieve the outputs in the following ways:
- Save the analysis results to a feature class with the export method.
- Directly read the results with the searchCursor method.
- Retrieve the results in Apache Arrow format with the toArrowTable method.
- Save the analysis results to a .zip file that can be used in other applications, such as ArcGIS Navigator.
- Save the analysis results to a layer file or package for debugging purposes.
This topic describes each of these options in more detail so you can choose the one appropriate for your needs.
Note:
This topic uses Route and OD Cost Matrix analysis as examples. The information provided here can be applied to any type of network analysis, with some exceptions that are noted where relevant.
Save results to a feature class
To save your analysis results directly to disk as they are returned by the solver, use the export method. All fields and rows for the designated output type are included.
The following code snippet shows how to save analysis results to disk using the export method.
# Solve the analysis
result = route.solve()
# Save results to disk using the export method
output_feature_class = "C:/data/io.gdb/Routes"
result.export(arcpy.nax.RouteOutputDataType.Routes, output_feature_class)
Learn more about the export method for route analysis in the Methods section of the RouteResult object's documentation.
See a complete list of analysis output types and their schemas for a route analysis
Read results
The searchCursor method can be used to directly access outputs row by row. This is useful if you only need to retrieve specific fields from the output or if you want to insert the results directly into some other system without saving the entire output table to disk.
For example, perhaps in your Route analysis, you only need to retrieve the total miles traveled for each route so you can include that information in a report. Use the searchCursor method to retrieve the Total_Miles field for each row.
The following code snippet shows how to retrieve the values of certain fields in the output using the searchCursor method. In this example, the names of routes longer than 10 miles are printed to the console.
# Solve the analysis
result = route.solve()
# Retrieve specific fields of interest using a searchCursor
for row in result.searchCursor(arcpy.nax.RouteOutputDataType.Routes, ["Name", "Total_Miles"]):
# Retrieve the name and mileage for each route
route_name = row[0]
route_miles = row[1]
# Print the route's name if the route's total mileage is greater than 10 miles
if route_miles > 10:
print(route_name)
You can use the searchCursor method to read analysis results into a pandas dataframe for further analysis.
The following code snippet shows how to use the searchCursor method to construct a pandas dataframe from the analysis results.
import pandas as pd
# Solve the analysis
result = route.solve()
# Read the results into a pandas dataframe
fields = ["Name", "Total_Miles"]
with result.searchCursor(arcpy.nax.RouteOutputDataType.Routes, fields) as cur:
df = pd.DataFrame(cur, columns=fields)
# Do some further analysis...
You can access the geometry of outputs using some special shape tokens. For example, using the SHAPE@JSON token allows you to retrieve a JSON representation of the shape. Use the SHAPE@XY token to retrieve a tuple of X and Y coordinates for a point in the spatial reference specified by the solver result object's spatialReference property.
Tip:
Use the result object's fieldNames method to retrieve a list of fields included in the analysis output class. Learn more about the fieldNames method for Route analysis output in the Methods section of the RouteResult object's documentation.
Learn more about the searchCursor method for Route analysis in the Methods section of the RouteResult object's documentation.
Learn more about the SolverResultSearchCursor object
See a complete list of analysis output types and their schemas for a Route analysis
Retrieve results in Apache Arrow format
For OD Cost Matrix analysis, you can retrieve the Lines output as an Apache Arrow Table object and save the results to a file using the toArrowTable method. Apache Arrow can be used to efficiently store and read large amounts of data and can easily work with and convert between many other data formats popular in data science.
Caution:
The toArrowTable method is only available for the OD Cost Matrix solver.
The following code snippet shows how to retrieve the results of an OD Cost Matrix analysis as an Arrow table with the toArrowTable method and uses the Arrow table to calculate the number of destinations reached by each origin.
# Solve the analysis
result = od_matrix.solve()
# Retrieve the Arrow table using the toArrowTable method
arrow_table = result.toArrowTable(
arcpy.nax.OriginDestinationCostMatrixOutputDataType.Lines,
["OriginOID"]
)
# Count the number of destinations reached by each origin.
# The result is a pyarrow structured array.
counts = arrow_table["OriginOID"].value_counts()
# If desired, you can convert the Arrow table to a pandas dataframe
# or many other supported formats.
df = arrow_table.to_pandas(split_blocks=True, zero_copy_only=True)
If desired, you can specify an output file in which to store the analysis results permanently. This file can be used in further analysis later.
The following code snippet shows how to use the toArrowTable method to save the results to a file and how to read in the file for further analysis.
# Solve the analysis
result = od_matrix.solve()
# Using the toArrowTable method to save the OD Cost Matrix result permanently to a file.
result.toArrowTable(
arcpy.nax.OriginDestinationCostMatrixOutputDataType.Lines,
["OriginOID", "DestinationOID", "Total_Time", "Total_Distance"],
os.path.join(output_folder, "ODLines.arrow")
)
The following code snippet shows how to read in the saved file for further analysis.
import pyarrow
# Read the data from the file
with pyarrow.memory_map(os.path.join(output_folder, "ODLines.arrow"), 'r') as source:
batch_reader = pyarrow.ipc.RecordBatchFileReader(source)
table_from_file = batch_reader.read_all()
# Create a pandas dataframe using the records from the memory-mapped file using zero copy
df = table_from_file.to_pandas(split_blocks=True, zero_copy_only=True)
# Do some further analysis...
When working with very large datasets, you may need to use the max_batch_size parameter to prevent out-of-memory errors when the analysis results are written out. This parameter specifies the maximum number of records to include in a single record batch in the output Arrow table. When an Arrow table or file containing multiple record batches is converted to another format, such as a pandas dataframe, you may not be able to do a zero-copy read of the entire table or file. In a zero-copy read, the data can be accessed without additional serialization overhead to load it in RAM. In order to achieve this zero-copy read behavior, your code may need to handle one record batch at a time.
The following code snippet shows how to set the maximum batch size for the Arrow outputs when calling toArrowTable.
# Solve the analysis
result = od_matrix.solve()
# Using the toArrowTable method to save the OD Cost Matrix result permanently to a file.
# Use max_batch_size to prevent memory errors.
out_arrow_file = os.path.join(output_folder, "ODLines.arrow")
arrow_table = result.toArrowTable(
arcpy.nax.OriginDestinationCostMatrixOutputDataType.Lines,
["OriginOID", "DestinationOID", "Total_Time", "Total_Distance"],
out_arrow_file,
max_batch_size=1000000 # Limit the output batches to one million records
)
The following code snippet shows how to read in and work with a file containing multiple record batches.
import pyarrow
# Process the OD Cost Matrix results in batches
with pyarrow.memory_map(os.path.join(output_folder, "ODLines.arrow"), 'r') as source:
batch_reader = pyarrow.ipc.RecordBatchFileReader(source)
for i in range(batch_reader.num_record_batches):
rb = batch_reader.get_batch(i)
# Convert this record batch to a pandas dataframe using zero copy
df = rb.to_pandas(split_blocks=True, zero_copy_only=True)
# Do some further analysis...
Learn more about the toArrowTable method for OD Cost Matrix analysis in the Methods section of the OriginDestinationCostMatrixResult object's documentation.
See a complete list of analysis output types and their schemas for an OD Cost Matrix analysis
Retrieve a route data .zip file
For Route, Closest Facility, and Vehicle Routing Problem analysis, you can export the result to a route data .zip file. The .zip file can be shared as route layer items in ArcGIS Online or ArcGIS Enterprise using the Share As Route Layers tool.
A route layer item can be used by various applications, such as ArcGIS Navigator to provide route guidance for mobile workers, the Directions pane in Map Viewer Classic to further customize the route contained in the route layer, and ArcGIS AllSource to create a route analysis layer from a route layer.
The following code snippet shows how to save a route data .zip file with the saveRouteData method and share it to your portal with the ShareAsRoute Layers function.
# Solve the analysis
result = route.solve()
# Export the results to a route data .zip file
out_zip = "C:/data/RouteData.zip"
result.saveRouteData(out_zip)
# Share the route data zip file as route layers to your portal
arcpy.nax.ShareAsRouteLayers(
out_zip,
summary='Tuesday restaurant inspection routes',
tags='Tuesday',
route_name_prefix='TuesdayRestaurants',
portal_folder_name='RouteLayers',
share_with='MYGROUPS',
groups='Drivers'
)
Caution:
To successfully run the saveRouteData method, the allowSaveRouteData property on the solver object must be set to True.
Learn more about the saveRouteData method for Route analysis in the Methods section of the RouteResult object's documentation.
Save a layer file or package
You can save your analysis settings and results to a layer file or layer package using the saveAsLayerFile method and open and examine the resulting layer in ArcGIS AllSource. This is primarily intended for debugging your analysis.
You can choose to save as either a .lyr layer file compatible with either ArcGIS Desktop or ArcGIS AllSource or a .lpkx layer package compatible with ArcGIS AllSource only. The output type depends on the file extension you use when specifying the method's file_name parameter. Layer packages include the analysis data but do not include the network data source.
Legacy:
Layer files with the .lyr extension do not have a travel mode property. The individual settings making up the travel mode will be preserved in the saved layer, but the name of the travel mode used for the analysis will be lost.
The following code snippet shows how to save the analysis results as a layer package using the saveAsLayerFile method.
# Solve the analysis
result = route.solve()
# Save the results to a layer package for debugging purposes
out_lpkx = "C:/data/RouteAnalysis.lpkx"
result.saveAsLayerFile(out_lpkx)
Note:
To successfully run the saveAsLayerFile method, the allowSaveLayerFile property on the solver object must be set to True.
Learn more about the saveAsLayerFile method for Route analysis in the Methods section of the RouteResult object's documentation.