GetCount not working properly

4111
19
05-04-2012 07:03 AM
AbbyFlory
New Contributor
Hi,

I am using PyScripter to write code that does the following:

1) Turn an input feature class into a feature layer ("Input_FL"),
2) Turn an ancillary-data feature class into a feature layer ("Ancill_FL"),
3) For each row in "Input_FL", select "Ancill_FL" within 10km,
4) Set Count = arcpy.GetCount_management(Ancill_FL).getOutput(0),
5) Update specific field in row with Count value,
6) Once all rows have finished, create new feature class from feature layer "Input_FL".

Upon checking the results, the majority of counts are correct, but some are off by one or two.  My "checking" consists of performing the selection manually in ArcMap and viewing the selected items counted in the attribute table (along with visual inspection).

Has anyone else experienced this problem?  And does anyone know why arcpy vs. manual selection would produce different counts, and/or why my arcpy results were correct most of the time, but incorrect some of the time? 

Thanks in advance for any help!
Tags (2)
0 Kudos
19 Replies
DuncanHornby
MVP Notable Contributor
Abby,

Are your datasets in different coordinate systems (projections)? This may account for the difference. I think some tools perform best when the data is NOT in decimal degrees.

Duncan
0 Kudos
AbbyFlory
New Contributor
Thanks for your reply - both datasets are in the same projection (Albers Equal Area Conic), which is in meters.  Any other thoughts?  Thanks again!
0 Kudos
ChrisSnyder
Regular Contributor III
Since you are looping through your features, are you sure that some of the subsequent loops aren't in effect overwritting some of the previous selections/counts?

Can you post the code you are using?
0 Kudos
AbbyFlory
New Contributor
Yea, definitely... I left out my time-keeping bits and a some irrelevant processes in the beginning, but here's the rest:

# Imports...
import time
print "Start time:",time.ctime()
StartSecs = time.clock()
import Functions
import arcpy
import sys
import traceback
from arcpy import env

# Environments...
env.workspace = "C:/AF_WorkingFiles/AgHealth_Iowa/Databases/AHS_NitrateWells.mdb"

# User-defined variables...
Wells2 = "C:/.../FC_Wells2"  #Input wells feature class
Wells3 = "C:/.../FC_Wells3"  #Output feature class
AFOs = "C:/.../AFOs"
AFO_Confine = "C:/.../AFO_ConfinementOnly"
AFO_Feedlot = "C:/.../AFO_FeedlotOnly"
AFO_Mixed = "C:/.../AFO_MixedOnly"
Hogs = "C:/.../Hogs"

try:

    # Delete fields if they exist...
    (left out)

    # Run near tool...
    (left out)

    # Create feature layer...
    arcpy.MakeFeatureLayer_management(Wells2,"Wells2Lyr")

    # Add count fields...
    L2 = ["Count_10kmAFOs","Count_10kmConfmnts","Count_10kmFeedlots", \
    "Count_10kmMixed","Count_10kmHogs"]
    for item in L2:
        arcpy.AddField_management("Wells2Lyr",item,"LONG")

    # Create ancillary feature layers...
    arcpy.MakeFeatureLayer_management(AFOs,"AFOLyr")
    arcpy.MakeFeatureLayer_management(AFO_Confine,"ConfineLyr")
    arcpy.MakeFeatureLayer_management(AFO_Feedlot,"FeedLyr")
    arcpy.MakeFeatureLayer_management(AFO_Mixed,"MixedLyr")
    arcpy.MakeFeatureLayer_management(Hogs,"HogLyr")

    # ASSIGN COUNTS TO FIELDS
   
    # Set variables...
    SelNew = "NEW_SELECTION"
    SelDist = "WITHIN_A_DISTANCE"
    SelAddTo = "ADD_TO_SELECTION"
    SelClear = "CLEAR_SELECTION"

    # Assign counts to each row...
    cur1 = arcpy.UpdateCursor("Wells2Lyr")
    for row in cur1:
        UnqKey = row.Concat_DatasetPrimkey

        # Select well at row...
        WhereClause = '[Concat_DatasetPrimkey]' + " = '" + UnqKey + "'"
        arcpy.SelectLayerByAttribute_management("Wells2Lyr",SelNew,WhereClause)

        # Select ancillary layers within 10km...
        arcpy.SelectLayerByLocation_management("AFOLyr",SelDist,"Wells2Lyr",10000,SelAddTo)
        arcpy.SelectLayerByLocation_management("ConfineLyr",SelDist,"Wells2Lyr",10000,SelAddTo)
        arcpy.SelectLayerByLocation_management("FeedLyr",SelDist,"Wells2Lyr",10000,SelAddTo)
        arcpy.SelectLayerByLocation_management("MixedLyr",SelDist,"Wells2Lyr",10000,SelAddTo)
        arcpy.SelectLayerByLocation_management("HogLyr",SelDist,"Wells2Lyr",10000,SelAddTo)

        # Count selected records in each layer and assign to appropriate fields...
        row.Count_10kmAFOs = int(arcpy.GetCount_management("AFOLyr").getOutput(0))
        row.Count_10kmConfmnts = int(arcpy.GetCount_management("ConfineLyr").getOutput(0))
        row.Count_10kmFeedlots = int(arcpy.GetCount_management("FeedLyr").getOutput(0))
        row.Count_10kmMixed = int(arcpy.GetCount_management("MixedLyr").getOutput(0))
        row.Count_10kmHogs = int(arcpy.GetCount_management("HogLyr").getOutput(0))
        cur1.updateRow(row)

        # Clear all selected records...
        arcpy.SelectLayerByAttribute_management("Wells2Lyr",SelClear)
        arcpy.SelectLayerByAttribute_management("AFOLyr",SelClear)
        arcpy.SelectLayerByAttribute_management("ConfineLyr",SelClear)
        arcpy.SelectLayerByAttribute_management("FeedLyr",SelClear)
        arcpy.SelectLayerByAttribute_management("MixedLyr",SelClear)
        arcpy.SelectLayerByAttribute_management("HogLyr",SelClear)

    # Create final feature class from results...
    arcpy.CopyFeatures_management("Wells2Lyr",Wells3)

finally:  
    # Delete cursor...
    del cur1, row


Thoughts??
0 Kudos
ChrisSnyder
Regular Contributor III
Can you repost using the code tag button (#)? Makes it easier to ready as indents are critical in Python...
0 Kudos
curtvprice
MVP Esteemed Contributor
And does anyone know why arcpy vs. manual selection would produce different counts, and/or why my arcpy results were correct most of the time, but incorrect some of the time?


The tool SelectLayerByLocation and spatial joins are different algorithms. There are differences in what the tolerances used are and the algorithms. To get consistent results, you should use the same tool with the same options and tolerances.
0 Kudos
DuncanHornby
MVP Notable Contributor
Abby,

I must emphasise Chris's comment about placing your code in the code tags (#) as this makes reading your code easier. This is even more important with Python as indentation is everything! Look at your code you posted how are we to tell when code is outside a loop? Anyway...

I have two ideas:

  1. Is the code where you clear existing selections outside the For loop? Can't tell as there is no formating...

  2. In your selection code arcpy.SelectLayerByLocation_management("AFOLyr",SelDist,"Wells2Lyr",10000,SelAddTo) you are doing a selection and adding it the existing selection. Was that your intention? Are you not trying to do a new selection for each iteration of the cursor? If so replace SelAddTo with SelNew.

DUncan
0 Kudos
AbbyFlory
New Contributor
Sorry - I knew it would be difficult to read, but I didn't know how to get around it (i.e., I didn't know about the # button ...I'm new to posting forum code).  My apologies!  Here's another go at it... 

NOTE: In the code below I have simplified what's happening.  This code is where I began, and produced the same count discrepancies as the more complex code.  Perhaps this is a better to start since it produced the same problematic result...

CURTIS: I use SelectLayerByLocation in my code and then use SelectByLocation manually in ArcMap for the check.

DUNCAN: Regarding the selection type, I use "Add to" because I have also selected one row in the table.  So, for each row in the table, I select the row (i.e. a single feature), add to this selection by selecting ancillary data within 10,000m of this feature, then count the selected ancillary data and write this value to the appropriate field in the row.  Below I have included only one ancillary data layer, because as stated above, this produces the same count discrepancies.  When selecting features within 10,000m from multiple ancillary data layers, my "GetCount" tool is specific to each ancillary data layer - therefore it returns the count for each layer and not the count of everything selected.  Hope this helps clear up my reasoning for using "Add to" - if not just let me know!

I appreciate your continued help with this!


# Imports...
import arcpy
import sys
import traceback
from arcpy import env

# Environments...
env.workspace = "C:/AF_WorkingFiles/AgHealth_Iowa/Databases/AHS_NitrateWells.mdb"

# User-defined variables...
Wells2 = "C:/.../FC_Wells2" #Input feature class
Wells3 = "C:/.../FC_Wells3" #Output feature class
AFOs = "C:/.../AFOs"

try:

    # Delete fields if they exist...
    #(left out)

    # Create feature layer...
    arcpy.MakeFeatureLayer_management(Wells2,"Wells2Lyr")

    # Add count fields...
    L2 = ["Count_10kmAFOs","Count_10kmConfmnts","Count_10kmFeedlots", \
    "Count_10kmMixed","Count_10kmHogs"]
    for item in L2:
        arcpy.AddField_management("Wells2Lyr",item,"LONG")

    # Create ancillary feature layer...
    arcpy.MakeFeatureLayer_management(AFOs,"AFOLyr")

    # Set variables...
    SelNew = "NEW_SELECTION"
    SelDist = "WITHIN_A_DISTANCE"
    SelAddTo = "ADD_TO_SELECTION"
    SelClear = "CLEAR_SELECTION"

    # Assign counts to each row...
    cur1 = arcpy.UpdateCursor("Wells2Lyr")
    for row in cur1:
        UnqKey = row.Concat_DatasetPrimkey

        # Select feature at row...
        WhereClause = '[Concat_DatasetPrimkey]' + " = '" + UnqKey + "'"
        arcpy.SelectLayerByAttribute_management("Wells2Lyr",SelNew,WhereClause)

        # Select ancillary layer within 10km...
        arcpy.SelectLayerByLocation_management("AFOLyr",SelDist,"Wells2Lyr",10000,SelAddTo)

        # Count selected records in each layer and assign to appropriate fields...
        row.Count_10kmAFOs = int(arcpy.GetCount_management("AFOLyr").getOutput(0))
        cur1.updateRow(row)

        # Clear all selected records...
        arcpy.SelectLayerByAttribute_management("Wells2Lyr",SelClear)
        arcpy.SelectLayerByAttribute_management("AFOLyr",SelClear)

    # Create final feature class from results...
    arcpy.CopyFeatures_management("Wells2Lyr",Wells3)

except: #(error handling specifics listed here)

finally:
    del cur1, row
0 Kudos
DuncanHornby
MVP Notable Contributor
Abby,

Don't know if this will help but if you add a selectbylocation tool to model builder fill it in and export it to Python one sees how the tool parameters should be completed.

For selectbylocation the distance also includes its units as shown below:

arcpy.SelectLayerByLocation_management("layer1","WITHIN_A_DISTANCE", "layer2","100 Meters", "ADD_TO_SELECTION")


Still don't get your logic to why you are adding to a selection, for this line you are adding to the selection of "AFOLyr"

# Select ancillary layer within 10km...
arcpy.SelectLayerByLocation_management("AFOLyr",SelDist,"Wells2Lyr",10000,SelAddTo)


which you then clear with this line:

arcpy.SelectLayerByAttribute_management("AFOLyr",SelClear)


Duncan
0 Kudos