1

I would like to preface this by saying that I am very new to python and its capabilities. So my problem is that while using the in_memory work space I encountered some limitations in querying the minimum value for a field. My workaround for this was to create a dictionary, then use a the search cursor to find the minimum distance. My method returns the results that I am looking for but I have not been able to incorporate these results into my selection. Below is a snippet of the code I am currently using:

# Process: Near
    arcpy.Near_analysis(newStationLayer, targetPoint, "", "NO_LOCATION", "NO_ANGLE", "")
    nearDist = {}
    with arcpy.da.SearchCursor(newStationLayer,("OID@","NEAR_DIST")) as cur:
        for row in cur:
            nearDist[row[0]] = row[1]

    arcpy.AddMessage("Near distances: %s"%str(nearDist))


    ## arcpy.AddWarning(min(nearDist.iteritems(),key=operator.itemgetter))
    lowestOID = min(nearDist,key=nearDist.get)
    arcpy.AddWarning(lowestOID)

    arcpy.SelectLayerByAttribute_management()
  • Are you asking what goes inside the () for the SelectLayerByAttribute line? – GeoJohn Dec 16 '15 at 15:23
  • Yes that is what I am trying to determine. I have tried many different configurations but to no avail.Its probably something really simple that I'm just missing when thinking it through. – wdingus Dec 16 '15 at 15:25
2

I always do this using a function that I originally found on stack exchange. It builds a where clause for you, and works with lists. It's nice, because it uses the add field delimiters function and therefore you dont have to wory about what type of data you are using (shapefile, fgdb, etc.). Just add this to your code somewhere and then call the function to to create your where clause.

def buildWhereClause(table, field, valueList):                     
    fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(table).path, field) 
    fieldType = arcpy.ListFields(table, field)[0].type                            
    if str(fieldType) == 'String':                                                
        valueList = ["'%s'" % value for value in valueList]                             
    whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(map(str, valueList)))        
    return whereClause

When you need your where clause:

whereClause = buildWhereClause(newStationLayer, "OBJECTID", [lowestOID])

And then:

arcpy.SelectLayerByAttribute_management(newStationLayer, "NEW_SELECTION", whereClause)

I did the selection parameters from memory, if it's not quite right you should at least get the idea.

  • As a side note. I have this function as part of a module of custom functions that I import for almost every script I write. This way I don't have to add it everytime, I just import the module and call it when needed. – GeoJohn Dec 16 '15 at 15:45
2

A really simple way to get the minimum value is to use TableToNumPyArray to convert your table to a numpy array then use numpy functions.

from arcpy.da import TableToNumPyArray
import numpy
na = TableToNumPyArray(newStationLayer, "NEAR_DIST")
numpy.min(na['NEAR_DIST'])

You can combine this directly with SelectLayerByAttribute_manager.

from arcpy.da import TableToNumPyArray
import numpy
field = "NEAR_DIST"
na = TableToNumPyArray(newStationLayer, field)
arcpy.SelectLayerByAttribute_management(newStationLayer, where_clause='"{}" = {}'.format(field, numpy.min(na[field])))

In that last statement, I am using the string format function to insert my field name into the where clause and to insert the results of calling numpy.min on my table array. For example, if your minimum value was 80.0, the where clause would become '"NEAR_DIST" = 80.0'.
If you get the error:

ExecuteError: Failed to execute. Parameters are not valid.
The value cannot be a feature class
ERROR 000840: The value is not a Raster Layer.
ERROR 000840: The value is not a Mosaic Layer.
Failed to execute (SelectLayerByAttribute).

It means that newStationLayer is a direct reference to a feature class and not a layer that you can apply a selection to. You will have to add something like:

layer = arcpy.MakeFeatureLayer_management(newStationLayer)
arcpy.SelectLayerByAttribute_management(layer, where_clause='"{}" = {}'.format(field, numpy.min(na[field])))  

I just had a chance to test this, and this is the right format for an in_memory where clause. Your reference to newStationLayer needs to be a reference to the layer in the map though and not a direct reference to the in_memory feature class! (Otherwise you will get the error I talked about above. arcpy.MakeFeatureLayer_management will add a new layer to the map using your in_memory feature class.)

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.