2

I am trying to make a script in Python (or Model Builder in ArcGIS) for correcting addresses.

I have a point shapefile with the addresses (it has X and Y, and fields for "number", "street name", and a unique code for locality), and a line shapefile with the name of the streets and also the unique locality code (we assume that there are no errors in the streets shapefile).

Example of errors I have to find:

  • in the same locality I can't have two points with the same number on the same street
  • no major leaps between numbers (for example the number 32 between 12 and 16)
  • only even numbers on a side of the street and only odd numbers on the other side
  • isolated numbers on the same street (ex: 2-3 km away from the next point on the same street)
  • etc.

I'll have to divide it into many sub-problems and try to fix them separately.

Do you have any suggestions about how I should proceed?

  • Welcome to the site ryan. Could you please refine the question into a single answerable question? Remember, you can always ask more quesions if you cannot find the answer in the archives. As this question stands, it is likely to be closed as being too broad. You can find more details on how to ask GIS SE type questions here: gis.stackexchange.com/help – Aaron Oct 20 '14 at 20:59
1

First, I'm skipping "only even numbers on a side of the street and only odd numbers on the other side" because the code for this might get a bit complicated. And because I'm not sure how to accomplish this task. Anyways, let's break these down. Python is my method of choice.

  • in the same locality I can't have two points with the same number on the same street

For this you are going to want to make use of a SearchCursor and a list. The type I use is for ArcGIS 10.1 and beyond. There is another type if you are using an older version of ArcGIS.

Try this:

shpfile = r"shape\file\full\path"

LocalityFldName = "locality"
NumberFldName = "num"
StreetFldName = "street"

import arcpy

li = []

flds = [LocalityFldName, NumberFldName, StreetFldName]
cursor = arcpy.da.SearchCursor (shpfile, flds)
for row in cursor:
    if not row[0] + str(row[1]) + row[2] in li[]:
        li.append(row[0] + str(row[1]) + row[2])
    else:
        print "Found double record"
        print row[0], row[1], row[2]
del row
del cursor
  • no major leaps between numbers (for example the number 32 between 12 and 16)

There is probably no perfect way to do this, given how varied the spatial relationships of parcels can be. Here is one method to get closer though, that may or may not work for you. In the code below, I first create a list of streets from the street name field using a cursor. I then iterate through this list of streets and create two layer files. One I will select an individual feature to be analyzed from using select by attribute, and the other I will select neighboring parcels from using select by location. I check if there are three features selected (initial and two neighbors) (this will probably not be a perfect method), and if so I perform a check to see if the neighboring street values are both smaller than the value in the feature being checked. You can mess a bit with this logic to see what works best for you.

shpfile = r"shape\file\full\path"

LocalityFldName = "locality"
NumberFldName = "num"
StreetFldName = "street"

import arcpy
arcpy.env.overwriteOutput = True

flds = [LocalityFldName, NumberFldName, StreetFldName, "OID@"]

#Get list of unique street names with searchcursor
streetsli = []
cursor = da.SearchCursor (shpfile, [StreetFldName])
for row in cursor:
    if not row[0] in streetsli:
        streetsli.append (row[0])
del row
del cursor

for street in streetsli:
    #Make layer for each stret
    sql = '"' + StreetFldName + '" = \'' + street + "'"
    #Make feature layer to iterate through features
    arcpy.MakeFeatureLayer_management (shpfile, "lyr", sql)
    #Make feature layers for neighbor selection
    arcpy.MakeFeatureLayer_management (shpfile, "neighborlyr", sql)
    cursor = arcpy.da.SearchCursor ("lyr", flds)
    OIDFld = arcpy.Describe ("lyr").OIDFieldName
    for row in cursor:
        #Select single feature
        sql = '"' + OIDFld + '" = ' + str(row[3])
        arcpy.SelectLayerByAttribute_management ("lyr", "", sql)

        #Select neighbors
        arcpy.SelectLayerByLocation_management ("neighborlyr", "", "lyr")

        #Check if three features are selected (selection feature plus two neighbors)

        if int(arcpy.GetCount_management("neighborlyr").getOutput(0)) == 3:

            first = True
            #Get two neighboring street values
            ncursor = arcpy.da.SearchCursor ("neighborlyr", [NumberFldName])
            for nrow in ncursor:
                #Make sure row is not same as initial street number
                if nrow[0] != row[1]:
                    if first == True:
                        val1 = nrow[0]
                        first = False
                    else:
                        val2 = nrow[0]
            del nrow
            del ncursor


            #Check if initial street number value is greater than both neighboring street values
            if row[2] > val1 and row[2] > val2:
                print "Something strange with", row[0], row[1], street

isolated numbers on the same street (ex: 2-3 km away from the next point on the same street)

Look into accomplishing this with SelectLayerByLocation_management or Near_analysis or PointDistance_analysis.

I hope this helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.