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 ?
Solved! Go to Solution.
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]
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.
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.
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]
def FindLabel ( [SR], [Shape_Length] ):
myLength = [Shape_Length]
if myLength > 150 :
return [SR] + "-" + str(myLength)
else:
return [SR] + "++" + str(myLength)
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.
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]
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.
.
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]
line 11 ... in ["999"] should be a list or change it to an equality check