Чи можна мітки для точок, що перекриваються, об'єднати / об'єднати в одну мітку?


12

У мене є бали, що відображають вибіркові місця. Часто в одному і тому ж місці будуть взяті кілька зразків: кілька точок з однаковим розташуванням, але різні ідентифікатори вибірки та інші атрибути. Я хотів би позначити всі точки, які знаходяться спільно з однією міткою, у складеному тексті перелічені всі зразки ідентифікаторів усіх точок у цьому місці.

Чи можливо це в ArcGIS, використовуючи звичайний двигун маркування або Maplex? Я знаю, що міг би обійти це, створивши новий шар із усіма зразками ідентифікаторів для кожного місця в одному значенні атрибута, але я хотів би уникати створення нових даних лише для маркування.

В основному я хочу піти з цього:

введіть тут опис зображення

До цього (для верхньої точки):

введіть тут опис зображення

Не роблячи жодного ручного редагування міток.


Скільки балів у вашому наборі даних?
Hornbydd

Відповіді:


11

Один із способів зробити це - клонування шару, використання запитів визначення та маркування їх окремо, використання лише позиції мітки зліва вліво для першого шару та нижнього зліва для другого.

Додайте ціле число типу THEFIELD до шару та заповніть його, використовуючи вираз нижче:

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

Телефонуйте за телефоном:

FirstOrOthers( !Shape! )

Створіть копію шару в змістовій таблиці, застосуйте запит визначення THEFIELD = 1.

Застосувати запит визначення THEFIELD = 2 для вихідного шару.

Застосовуйте різні фіксовані розмітки міток

введіть тут опис зображення

ОНОВЛЕННЯ на основі коментарів до оригінального рішення:

Додайте поле COORD та заповніть його за допомогою

'%s %s' %(round( !Shape!.firstPoint.X,2),round( !Shape!.firstPoint.Y,2))

Підсумуйте це поле, використовуючи перше і останнє для мітки. Приєднайтеся до цієї таблиці до оригіналу, використовуючи поле COORD. Виберіть записи, де ялинки <> останні, і об'єднайте першу та останню мітку в новому полі, використовуючи

'%s\n%s' %(!Sum_Output_4.First_MUID!, !Sum_Output_4.Last_MUID!)

Використовуйте Count_COORD та THEFIELD для визначення 2 "різних шарів" та полів для позначення їх:

введіть тут опис зображення

Оновлення №2, натхнене рішенням @Hornbydd:

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 ""

ОНОВЛЕННЯ Листопад 2016 року, сподіваємось, триватиме.

Нижче вираз, перевірений на 2000 дубліках, працює як шарм:

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 "

Гей, ти зламав це! Приємно! Я знав, що там хтось хизується! Як я очікував, це дуже ітеративний процес, тому запускайте на великому наборі даних, і мітки вічно малюють (добре, що це було на моїх тестових даних). Я переробив ваш стиль коду, розширивши кілька рядків. Мені здається мінімалістським, всі по одній лінії важко дотримуватися.
Hornbydd

1
@Hornbydd дякую за зміни. Цю гайку важко було зламати через поведінку етикетки (двигуна?). Він розглядає всі параметри функції як рядки! Ось чому перший IF не працював без f = int ([FID]). Щодо швидкості, я ніколи не використовував би її на множині більше 50 балів. Він повинен бути перетворений в сценарій, який заповнює нове поле, пройшовши через набір даних лише два рази: 1) курсор пошуку для компіляції обох словників, 2) оновлення курсору для читання з них ПРИМІТКА: перші 3 рядки після оператора спробу застарілі, після публікації рішення I зрозумів, що їх можна безпечно зняти.
FelixIP

FYI У мене не було шансу повернутися до цього, але я планую дати своє рішення крутитись на наступному тижні або близько того. Існує також інше рішення (той, який я використовував у цьому випадку) без Python, я також опублікую відповідь про це.
Дан C

Потрапив на цю сторінку в геонет. Мені сподобалося розумне використання глобальних словників, потім подумав про це питання та додав посилання на нього.
Hornbydd

@Hornbydd так, це дуже розумно і детально, як і все від Річарда, і зробить величезне значення для мого (нашого) рішення. Можна вдосконалити її, видаливши кілька рядків, що включає найперший. Однак, виходячи з часу відповіді від ОП, схоже, він втратив інтерес, я також не турбую
FelixIP

4

Нижче - часткове рішення.

Це переходить у вираз позначення Advance. Це не дуже ефективно, тому я запитую про кількість балів у вашому наборі даних. Отже, для кожного рядка, який позначається, він створює 2 словники, dде ключ - XY, а значення - текст, а d2це - об’єктID та XY. Використовуючи цю комбінацію словників, вона може повернути єдину мітку, яка є об'єднанням з символами нового рядка, в моєму прикладі це об'єднання TARGET_FID. "sj" - назва шару в TOC.

import arcpy
def FindLabel ( [OBJECTID] ):
  ob = str([OBJECTID])
  mxd = arcpy.mapping.MapDocument("CURRENT")
  d ={}
  d2 = {}
  lyr = arcpy.mapping.ListLayers(mxd,"sj")[0]
  with arcpy.da.SearchCursor(lyr,["OID@","SHAPE@XY","TARGET_FID"]) as cursor:
    for row in cursor:
      objID = str(row[0])
      temp = row[1]
      tup = str(temp[0]) + "," + str(temp[1])
      d2[objID] = tup
      txt = str(row[2])
      if tup in d:
        v = d[tup] 
        v = v + "\n" + txt
        d[tup] = v
      else:
        d[tup] = txt  
  temp = d2[ob]
  return d[temp]

Чому це часткове рішення, це те, що це робиться для кожної точки, я не міг придумати, як би ви вимкнули всі інші складені точки. Саме тому я думаю, що остаточне рішення - це якийсь пітон, який створює новий шар з одиничних точок з єдиною міткою, побудованою із стека точок.

Нижче наведено результат 3-х складених точок, як ви бачите, що мітка створена для кожної точки, оскільки всі вони існують в одному місці.

Приклад

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.