[GIS] Select layer by attribute for entries in a dictionary (python)

arcgis-desktoparcpydictionarypython-2.7

I'm kinda new to python (and programming) and having trouble figuring out how to properly specify what I want to do.

Basically, my code compares names of well owners and orps owners and saves all orps that match a given well in a dictionary as

matches[fid of well] = fid of matching orps, fid of matching orps, etc.

Such that some wells are not included in the dictionary, some wells have one entry, and some wells have several entries.

Once created, I then need to:

  • select the well that the key of the dictionary is referring to
  • select the orps pts that the key is referring to
  • create a near table of matching orps for that given well. (this part I know how to do)

I guess I'm just unsure of the syntax required to do this. I'm sure the answer to this lies somewhere within the SQL query in the:

arcpy.SelectLayerByAttribute_management(in_layer, {selection_type}, {where_clause})

function, but I'm having trouble constructing the query. Can anyone give me a hand?

Full code:

import arcpy

arcpy.env.overwriteOutput = 1

# define a workspace
arcpy.env.workspace = r"C:\Users\tmc18\Desktop\comp_orps\NYS_Wells.gdb"

# Define input files
orps = r"C:\GIS\Madison_County_orps.gdb\orps_Cazenovia"
wells = r"C:\GIS\NYS_Wells.gdb\Madison_wells_cazenovia"

# Make a feature layer
arcpy.MakeFeatureLayer_management(orps, "orps1")
arcpy.MakeFeatureLayer_management(wells, "wells1")
wellsFL = "wells1"
orpsFL = "orps1"


# Create dictionary of last names of all well owners
well_owners = {}  
rows = arcpy.da.SearchCursor(wellsFL, ["OBJECTID", "OWNER_L"])  
for row in rows:
    well_owners[row[0]] = str(row[1])   
del rows

# create dictionary of addresses of ORPS pts
loc_info = {}
rows = arcpy.da.SearchCursor(orpsFL, ["OBJECTID", "LOC_NUM", "LOC_NAME", "PRINT_KEY"])
for row in rows:
    loc_info[row[0]] = str(row[1]+" "+row[2]+","+" "+row[3])
del rows

matches = {}


y = 0

# Create search cursor which will iterate through wells       
with arcpy.da.SearchCursor(wellsFL, ["OBJECTID"]) as cursor:
        for row in cursor:

            match_list = []
            # set well owner name for this record
            record = row[0]
            owner = well_owners[record]


            # create search cursor which will iterate through orps owners
            with arcpy.da.SearchCursor(orpsFL, ["OWNER_L", "OBJECTID"]) as orpscur:
                for row in orpscur:
                    # set orps owner name
                    orpsowner = row[0]
                    ID = row[1] 

                    # compare owner's names    
                    if owner != orpsowner:
                        pass


                    else:
                        y = y + 1
                        match_list.append(ID)

            matches[record] = match_list


print y, "total matches found"

Best Answer

This is more of a few tips than an answer. You mention that it takes a while to run. I have to things to point out that can save some you some time.

1) Your code goes through the wells once; no need to do it twice. You can get the list of well owner's names from the well_owners.values(). That's a python list of all the values in the dictionary. In your case you would get a list of string values. Thus we can chop:

# Create search cursor which will iterate through wells       
with arcpy.da.SearchCursor(wellsFL, ["OBJECTID"]) as cursor:
        for row in cursor:

            # set well owner name for this record
            record = row[0]
            owner = well_owners[record]
            matches[record] = []


            # create search cursor which will iterate through orps owners
            with arcpy.da.SearchCursor(orpsFL, ["OWNER_L", "OBJECTID"]) as orpscur:
                for row in orpscur:
                    # set orps owner name
                    orpsowner = row[0]
                    ID = row[1] 

                    # compare owner's names    
                    if owner != orpsowner:
                        pass


                    else:
                        x = x + 1
                        matches[record].append(ID)

to the following. This method removes iterating through the orpsFL with each well.

# create search cursor which will iterate through orps owners
with arcpy.da.SearchCursor(orpsFL, ["OWNER_L", "OBJECTID"]) as orpscur:
    for row in orpscur:
        # set orps owner name
        orpsowner = row[0]
        ID = row[1] 
        # see if orps owner is in list of well owner
        if orpsowner in well_names.values():
            x += 1
            matches[orpsowner].append(ID)

2) SQL has an IN operator that is very useful. You are adding to the selection for each matching OID. It's faster to say "OBJECTID IN (1,2,3,4,5)" than selecting 1, then 2, then 3, etc. So we can change:

for key in matches:
    arcpy.SelectLayerByAttribute_management(wellsFL, "NEW_SELECTION", "OBJECTID =    {}".format(key))
    for element in matches[key]:
        nextmatch = matches[key].pop()
        arcpy.SelectLayerByAttribute_management(orpsFL, "ADD_TO_SELECTION", "OBJECTID = {}".format(nextmatch))

to:

for key in matches:
    arcpy.SelectLayerByAttribute_management(wellsFL, "NEW_SELECTION", "OBJECTID =    {}".format(key))
    # tuple of ids to select
    id_select = tuple(matches[key])
    arcpy.SelectLayerByAttribute_management(orpsFL, "NEW_SELECTION", "OBJECTID in {}".format(id_select))

I hope I didn't change any variable names and that you find this helpful.