Arcmap Python Label Expression Function "Null"

8939
30
Jump to solution
11-02-2016 03:26 PM
DevinUnderwood2
Occasional Contributor

I am having difficulty with python parser label function to replace null values with "Unknown Plan" and leave everything else as is. The Unknown Plan is not displaying in the map label.

I have the following:

def FindLabel ( [PLAN] ):
    if  ([PLAN]) is  None:
         return "Unknown Plan"
    else:
        return [PLAN]

Any idea it is not working ?

0 Kudos
30 Replies
TedKowal
Occasional Contributor III

You cannot simply pass the geometry into a label string (At least I have never figured out  how) so you would have to do something like this:

import arcpy
lyrName = "AADT_2015"
shapeDict = {}
with arcpy.da.SearchCursor(lyrName, ("OID@","SHAPE@LENGTH")) as cursor:
   for row in cursor:
      shapeDict[row[0]] = row[1]

def FindLabel([OBJECTID]):
   oid = int([OBJECTID])
   if shapeDict[oid] > 50:
      return "BIG"
   else:
      return "Small"

Personally I feel that is over kill..... If I were doing it I would create a new field say myLength as a double... use the field calculator to calculate the segment length  (!shape.length! I believe )...then pass [myLength] to your label function as you wrote it above  using [myLength] instead of [SHAPE.LEN]

0 Kudos
DevinUnderwood2
Occasional Contributor

Thanks, I will look into this.

At a first look I don't see how all this can be included in a label expression. my goal is not needing to edit the actual data at all.

0 Kudos
TedKowal
Occasional Contributor III

Sometimes a little editing can go a long ways in saving time and headaches....     unless you want to run the cursor script the only other automatize way I can think of is to write a python script that activates on mxd open event which would populate/referesh the "myLength" column for you -- but that would involve writing an add-in.

0 Kudos
DevinUnderwood2
Occasional Contributor

I am testing it out by taking your suggestion of adding a new length field and using the following expression.

It is not working as I think I have to specify when it is a non text field. Is that correct ?

def FindLabel ( [LENGTH] , [PLAN]  ):
    if Double ( [LENGTH] )   > 50:
        return [PLAN]
    else:
        return [PLAN]
0 Kudos
TedKowal
Occasional Contributor III
def FindLabel ( [SR], [Shape_Length]  ):
   myLength = [Shape_Length]
   if myLength > 150 :
      return [SR] + "-" + str(myLength)
   else:
       return [SR] + "++" + str(myLength)
0 Kudos
curtvprice
MVP Esteemed Contributor

Another downside of calculating labels on the fly is the huge performance hit you can get if your labeling logic is complex. A middle way would be to copy your table locally (or to in_memory), calculate text labels using a cursor, join your features to the table and label using the text field. I know it sounds difficult but if you really don't want to edit your data that may be a valid approach.

DevinUnderwood2
Occasional Contributor

I went ahead with not adding an additional field. I am not concerned with performance issues.

I arrived at the following at it does exactly what I wanted, thanks for everyone's input.

 

## The following label expression function is used to display labels for the main water lines.

Specifically, labeling water lines that have not been assigned Plan info, with “Plan ?”

Also, any water lines that are attributed as ABANDON will not display a label.

Lastly, all other water lines will be labeled/displayed as is.

Note: Displayed labels only if water main lines are greater than 50 feet.

 

 

lyrName = " Main Lines Plan Label"
shapeDict = {}
with arcpy.da.SearchCursor(lyrName, ("OID@","SHAPE@LENGTH")) as cursor:
   for row in cursor:
      shapeDict[row[0]] = row[1]
 
def FindLabel([OBJECTID],[PLAN], [AGENCY]):
   oid = int([OBJECTID])
   if [AGENCY] == "ABANDON":
       return None
   elif [PLAN] in  (None, " ") and shapeDict[oid] > 50 :
       return "Plan ?"
   elif shapeDict[oid] > 50 :
       return [PLAN]

I have the following as well but that last line is giving me problems. If I use else without the > 50 condition, it is fine.

## The following label expression function is used to display labels for the main water lines.

Any water lines that are attributed as ABANDON will not display a label.

Any water lines that are attributed as unknown(999) will be labeled as “Size ?”

Also, water lines that are attributed as NULL (None) will be labeled as “Size ?”

Lastly, all other water lines will be labeled/displayed as is.

Note: Displayed labels only if water main lines are greater than 50 feet.

Note: '\x22' Python syntax is used to allow for double quotes in the label expression to represent inches.

 

lyrName = "Main Lines Diameter & Material Label"
shapeDict = {}
with arcpy.da.SearchCursor(lyrName, ("OID@","SHAPE@LENGTH")) as cursor:
   for row in cursor:
       shapeDict[row[0]] = row[1]
 
def FindLabel ( [OBJECTID], [DIAMETER], [MATERIAL], [AGENCY] ):
    oid = int([OBJECTID])
    if [AGENCY] == "ABANDON":
        return None
    elif [DIAMETER] in "999" and shapeDict[oid] > 50:
        return "Size ?" +  '\x22' + " " + [MATERIAL]
    elif [DIAMETER] in  (None, " ") and shapeDict[oid] > 50:
        return "Size ?" +  '\x22' + " " + [MATERIAL]
   elif shapeDict[oid] > 50:
        return [DIAMETER]  +  '\x22' + " " + [MATERIAL]
curtvprice
MVP Esteemed Contributor

I have the following as well but that last line is giving me problems. If I use else without the > 50 condition, it is fine.

Are you sure the indentation is correct? You posted code without formatting so it is hard to know for sure. The last elif line must be exactly aligned with the one above it.

0 Kudos
DevinUnderwood2
Occasional Contributor

.

I am successful in the flowing label expression to not show retired pipe lines.

lyrName = " Main Lines Plan Label"
shapeDict = {}
with arcpy.da.SearchCursor(lyrName, ("OID@","SHAPE@LENGTH")) as cursor:
   for row in cursor:
      shapeDict[row[0]] = row[1]
def FindLabel([OBJECTID],[PLAN], [AGENCY], [GIS_STATUS] ):
   oid = int([OBJECTID])
   if [AGENCY] == "ABANDON":
       return None
   elif [GIS_STATUS] == "Retired":
       return None 
   elif [PLAN] in  (None, " ") and shapeDict[oid] > 50 :
       return "Plan ?"
   elif shapeDict[oid] > 50:
       return [PLAN]

However, I am having trouble with not displaying labels for pipelines that have been attributed as retired for another  layer. Any ideas why?

lyrName = "Main Lines Diameter &  Material Label"
shapeDict = {}
with arcpy.da.SearchCursor(lyrName, ("OID@","SHAPE@LENGTH")) as cursor:
   for row in cursor:
       shapeDict[row[0]] = row[1]
def FindLabel ( [OBJECTID], [DIAMETER], [MATERIAL], [AGENCY], [GIS_STATUS] ):
    oid = int([OBJECTID])
    
 
    if [GIS_STATUS] == "Retired":
        return None
    elif [DIAMETER] in "999" and shapeDict[oid] > 50:
        return "Size ?" +  '\x22' + " " + [MATERIAL]
    elif [DIAMETER] in  (None, " ") and shapeDict[oid] > 50:
        return "Size ?" +  '\x22' + " " + [MATERIAL]
    else:
        return [DIAMETER] + '\x22' + " " + [MATERIAL]
0 Kudos
DanPatterson_Retired
MVP Emeritus

line 11  ... in ["999"]  should be a list or change it to an equality check

0 Kudos