1

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"
2
  • Can you post your code? – crmackey Jan 12 '15 at 16:00
  • @crmackey - I edited the post with my code. – carusot42 Jan 12 '15 at 16:07
1

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.

1
  • Many thanks for your input! I had actually realized the redundancy of the first block of code you edited, and my dictionary creation, and have condensed a lot of that into two for loops looking through those dictionaries. However, that "IN" operator is VERY useful - your example also will help immensely with the next part that I'm currently trying to add to this script. I truly appreciate your tips. As someone who's really trying to work on my python chops, little tips like this go a long way. I'll edit my post with my updated code shortly in case you're interested. – carusot42 Jan 14 '15 at 15:15
0

So, I solved this problem by saving the orps matches for each well in match dictionary as a list, and then selected each one using the list.pop() method, which treats the list as a stack and retrieves and removes the bottom value. The code above is the same, except...

matches = {}
x = 0

# 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)

print x, "total matches found"
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))
    arcpy.GenerateNearTable_analysis(wellsFL, orpsFL, "orps_near_well_{}".format(key), "5 kilometers", "LOCATION", "NO_ANGLE", "ALL", "5")
    arcpy.SelectLayerByAttribute_management(orpsFL, "CLEAR_SELECTION")     

and, it works perfectly, even if it does take a little bit. Some parts of the full code (such as the loc dictionary) are not 100% necessary right now, but will become more necessary as I flesh out this script to do more things (add the loc info of the best matching orps pt to the well table, etc).

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.