One way of doing this is cloning the layer, using definition queries and labelling them separately, using upper-left only label position for the first layer and lower-left for second.
Add THEFIELD type integer to layer and populate it using expression below:
aList=[]
def FirstOrOthers(shp):
global aList
key='%s%s' %(round(shp.firstPoint.X,3),round(shp.firstPoint.Y,3))
if key in aList:
return 2
aList.append(key)
return 1
Call it by:
FirstOrOthers( !Shape! )
Create a copy of layer in the table of content, apply definition query THEFIELD=1.
Apply definition query THEFIELD=2 for original layer.
Apply different fixed label placement
UPDATE based on comments to original solution:
Add field COORD and populate it using
'%s %s' %(round( !Shape!.firstPoint.X,2),round( !Shape!.firstPoint.Y,2))
Summarise this field using first and last for label. Join this table back to original using COORD field. Select records where firs<>last and concatenate first and last label in a new field using
'%s\n%s' %(!Sum_Output_4.First_MUID!, !Sum_Output_4.Last_MUID!)
Use Count_COORD and THEFIELD to define 2 'different layers' and fields to label them:
Update #2 inspired by @Hornbydd solution:
import arcpy
def FindLabel ([FID],[MUID]):
f,m=int([FID]),[MUID]
mxd = arcpy.mapping.MapDocument("CURRENT")
dFids={}
dLabels={}
lyr = arcpy.mapping.ListLayers(mxd,"centres")[0]
with arcpy.da.SearchCursor(lyr,["FID","SHAPE@","MUID"]) as cursor:
for row in cursor:
FD,shp,LABEL=row
XY='%s %s' %(round(shp.firstPoint.X,2),round( shp.firstPoint.Y,2))
if f == FD:
aKey=XY
try:
L=dFids[XY]
L+=[FD]
dFids[XY]=L
L=dLabels[XY]
L=L+'\n'+LABEL
dLabels[XY]=L
except:
dFids[XY]=[FD]
dLabels[XY]=LABEL
Labels=dLabels[aKey]
Fids=dFids[aKey]
if f == Fids[0]:
return Labels
return ""
UPDATE November 2016, hopefully last.
Below expression tested on 2000 duplicates, works like charm:
mxd = arcpy.mapping.MapDocument("CURRENT")
lyr = arcpy.mapping.ListLayers(mxd,"centres")[0]
dFids={}
dLabels={}
fidKeys={}
with arcpy.da.SearchCursor(lyr,["FID","SHAPE@","MUID"]) as cursor:
for FD,shp,LABEL in cursor:
XY='%s %s' %(round(shp.firstPoint.X,2),round( shp.firstPoint.Y,2))
fidKeys[FD]=XY
if XY in dLabels:
dLabels[XY]+=('\n'+LABEL)
dFids[XY]+=[FD]
else:
dLabels[XY]=LABEL
dFids[XY]=[FD]
def FindLabel ([FID]):
f=int([FID])
aKey=fidKeys[f]
Fids=dFids[aKey]
if f == Fids[0]:
return dLabels[aKey]
return "
Best Answer
Approach 1: Maplex Remove Duplicates
First, make sure you are using the Maplex Label Engine by checking the box in the Labeling toolbar. You can also set the Maplex Label Engine to be the default in Customize > ArcMap Options > Data View tab > Default Labeling Properties.
Second, check the
Remove duplicates
box in the Label Density tab of the Placement Properties of the layer you are labeling. You can also customize the radius in which duplicates are searched.Approach 2: Label classes
If you can't use Maplex (as you've noted) or you are labeling coincident points by a field with unique values for each feature, we need to take a different approach. First, add a new integer field called
Label
to your attribute table.Second, in field calculator, flag duplicate records by running a special field calculator expression on your new field. Use the expression
isDuplicate(!Shape!)
, assumingShape
is the name of your geometry field, thePYTHON_9.3
parser, and the following Python code in the optional code block. This will flag the first instance of each geometry with a0
, duplicates with a1
, and null or invalid geometry with a-1
.Then, you can use label classes to only label features that have a
0
in theLabel
fieldvia a SQL query. This should remove duplicate labels.