Trying to create a OD matrix shapefile with data from centroids using Python

840
3
09-14-2021 01:45 PM
Joaquin_Osorio
New Contributor

Good morning.

I'm trying to create a OD matrix shapefile using Python. I can't use Network Analyst since I am using about 3100 Origin points and Destiny points. What I want is just the line shapefile, I don't care about distance or time travels. 

I have used a script I found in this thread: https://community.esri.com/t5/data-management-questions/is-there-a-way-to-connect-all-points-in-a/td...

While it works and I have my OD matrix, it has no data from the centroids, and then preparing the data for the analysis I'm working I find the problem that spatial join with the centroids to enrich data generates two flows from point 1 to point 9 instead a flow from 1-9 and the other one to 9-1.

What I thought is to directly enrich the data in the step that creates the lines, so I can have a column with the name of the origin centroid and another one with the name of the destination centroid.

In my case, the fields I want to add to the OD matrix are called 'ID_GRUPO','SUM_POB_AS','NOMBRE_CEL'. I tried this script but the result I got is again a OD matrix with just a field called ID which has always a value 0.

 

fc = 'celdas_centroids' # feature class

sr = arcpy.Describe(fc).spatialReference # spatial reference

lines = [] # output line list

geoms = [i[0] for i in arcpy.da.SearchCursor(fc,['SHAPE@','ID_GRUPO','SUM_POB_AS','NOMBRE_CEL'],spatial_reference=sr)] # point geometries

for geom1 in geoms: # loop through points

    for geom2 in geoms: # compare to points

        lines.append(arcpy.Polyline(arcpy.Array([[geom1.centroid,geom2.centroid]]),sr)) # create line

arcpy.CopyFeatures_management(lines,r'F:\matriz_celdas_od.shp') # output to feature class

 

Thank you very much for the help.

0 Kudos
3 Replies
DavidPike
MVP Frequent Contributor

Can you elaborate on this as I don't quite understand.

I find the problem that spatial join with the centroids to enrich data generates two flows from point 1 to point 9 instead a flow from 1-9 and the other one to 9-1.

0 Kudos
Joaquin_Osorio
New Contributor

Yes. I've tried to create a OD matrix using the Python script from the other thread I posted using a shapefile with +3200 centroids. As I result I get a shapefile with +10 million lines with only one field called "ID" with value 0. What I want is that every line has incorporated some fields from the centroids shapefile.

A solution I thought was in doing a spatial join one to many of the empty created line shapefile with my centroids shapefile. I get as a result a shapefile with +20 million lines, in which every line has the data from a centroid. There is also a field created when I do the spatial join called FID_ID, in which two lines have the same FID_ID value (making it a OD pair). Then I can summarize data to create a table with a single FID_ID value, the ID of the origin point and the ID of the destination point.

While this gives a very close result to what I want, there is only one improtant problem: the order the lines ID have in the spatial join shapefile and the order the summarized table is created.

To put an example, I have this in the spatial join shapefile:

FID 14 Origin centroid: ID 3

FID 14 Destiny centroid: ID 5

FID 15: Origin centroid ID 4

FID 15: Destiny centroid ID 5

FID 16: Origin centroid ID 5

FID 16: Destiny centroid ID 6

FID 300 Origin centroid: ID 3

FID 300 Destiny centroid: ID 5

FID 301: Origin centroid ID 4

FID 301: Destiny centroid ID 5

FID 302: Origin centroid ID 5

FID 302: Destiny centroid ID 6

 

I want FID 14 being a OD flow 3-5, FID 15 being 4-5, and FID 16 being 6-5, and then FID 300 being 5-3, FID 301 being 5-4, and FID 302 being 5-6.

 

But due to the order in the table and in the data summarization I'm forced to have two flows 3-5, 4-5, and 5-6. I don't know how to be able to get that.

 

So I thought in trying to create directly the OD matrix from the script, since the script already assumes an origin centroid, and a destination centroid, while the spatial join just assumes two points in ID order.

 

I've slightly edited the code to this:

 

fc = 'celdas_centroids' # feature class

sr = arcpy.Describe(fc).spatialReference # spatial reference

lines = [] # output line list

geoms = [i[0] for i in arcpy.da.SearchCursor(fc,['SHAPE@','ID_GRUPO','SUM_POB_AS','NOMBRE_CEL'],spatial_reference=sr)] # point geometries

for geom1 in geoms: # loop through points

for geom2 in geoms: # compare to points

lines.append(arcpy.Polyline(arcpy.Array([[geom1.centroid,geom2.centroid]]),['SHAPE@','ID_GRUPO','SUM_POB_AS','NOMBRE_CEL'],sr)) # create line

arcpy.CopyFeatures_management(lines,r'F:\matriz_celdas_od.shp') # output to feature class

 

I got a line shapefile with just the ID field and the SHAPE field. I want to have too the ID_GRUPO (centroid ID) field of the origin centroid and the centroid field of the destination centroid (plus two more fields of information about the origin centroid and two fields of information about the destiny centroid, from the fields SUM_POB_AS, and NOMBRE_CEL).

0 Kudos