У меня есть файл формы ESRI Point Shape с (среди других) поле nMSLINK и поле DIAMETER. MSLINK не уникален из-за пространственного соединения. То, что я хочу достичь, - сохранить только функции в шейп-файле, которые имеют уникальное значение MSLINK и наименьшее значение DIAMETER вместе с соответствующими значениями в других полях. Я могу использовать поисковый курсор для достижения этого (перебирать все функции и удалять каждую функцию, которая не соответствует, но это занимает много времени (> 75000 функций). Мне было интересно, может ли, например, numpy сделать трюк быстрее в ArcMap/arcpy.Сохраняйте наименьшее значение для каждого уникального идентификатора с дуговым/numpy
ответ
Я думаю, что такая обработка будет намного быстрее, если вы будете работать с памятью, а не взаимодействовать с arcgis. Например, поместив все строки сначала в объект python (возможно, namedTuple будет хорошим вариантом здесь) .Тогда вы можете узнать, какие строки вы хотите удалить или вставить.
Самый быстрый подход зависит от: a) если у вас много повторных строк (MSLINK), то самым быстрым будет вставка только тех, которые вы необходимо в новом слое. Или b) если строки, которые нужно удалить, всего несколько, по сравнению с общим количеством строк, то удаление происходит быстрее.
Для a) вам нужно получить все поля в кортеж, включая координаты точки, чтобы вы могли просто создать новый класс объектов и вставить новые строки.
# Example of Variant a:
from collections import namedtuple
# assuming the following:
source_fC# contains name of the fclass
the_path # contains path to the shape
cleaned_fC# the name of the cleaned fclass
# use all fields of source_fc plus the shape token to get a touple with xy
# coordinates (using 'mslink' and 'diam' here to simplify the example)
fields = ['mslink', 'diam', 'field3', ... ]
all_fields = fields + ['[email protected]']
# define a namedtuple to hold and work with the rows, use the name 'point' to
# hold the coordinates-tuple
Row = namedtuple('Row', fields + ['point'])
data = []
with arcpy.da.SearchCursor(source_fc, fields) as sc:
for r in sc:
# unzip the values from each row into a new Row (namedtuple) and append
# to data
data.append(Row(*r))
# now just delete the rows we don't want, for this, the easiest way, is probably
# to order the tuple first after MSLINK and then after the diamater...
data = sorted(data, key = lambda x : (x.mslink, x.diam))
# ... now just keep the first ones for each mslink
to_keep = []
last_mslink = None
for d in data:
if last_mslink != d.mslink:
last_mslink = d.mslink
to_keep.append(d)
# create a new feature class with the same fields as the source_fc
arcpy.CreateFeatureclass_management(
out_path=the_path, out_name=cleaned_fc, template=source_fc)
with arcpy.da.InsertCursor(cleaned_fc, all_fields) as ic:
for r in to_keep:
ic.insertRow(*r)
И для альтернативы b) Я бы просто получил 3 поля, уникальный идентификатор, MSLINK и диаметр. Затем создайте список удаления (здесь вам понадобятся только уникальные идентификаторы). Затем снова запустите класс объектов и удалите строки с идентификатором в списке delete. Чтобы быть уверенным, я бы сначала дублировал класс объектов и работал над копией.
Есть несколько шагов, которые вы можете предпринять, чтобы выполнить эту задачу более эффективно. Прежде всего, использование курсора анализатора данных, в отличие от старой версии курсора, увеличит скорость вашего процесса. Предполагается, что вы работаете в 10.1 или выше. Затем вы можете использовать сводную статистику, а именно ее способность находить минимальное значение, основанное на поле случая. Для вашего поля case будет nMSLINK.
В приведенном ниже коде создается таблица статистики со всеми уникальными значениями «nMSLINK» и соответствующим минимальным значением «ДИАМЕТР». Затем я использую таблицу select, чтобы выделять только строки в таблице, чье поле FREQUENCY не равно 1. Отсюда я повторяю свою новую таблицу и начинаю строить список строк, который будет составлять окончательный оператор sql. После этой итерации, я использую Python присоединиться к функции для создания SQL-строки, которая выглядит примерно так:
("nMSLINK" = 'value1' AND "DIAMETER" <> 624.0) OR ("nMSLINK" = 'value2' AND "DIAMETER" <> 1302.0) OR ("nMSLINK" = 'value3' AND "DIAMETER" <> 1036.0) ...
SQL, выбирает строки, в которых значение nMSLINK не являются уникальным и где значение ДИАМЕТРА не является минимальными. Используя этот SQL, я выбираю по атрибуту и удаляю выбранные строки.
Этот оператор SQL написан в предположении, что ваш класс объектов находится в базе геоданных файлов и что «nMSLINK» является строковым полем, а «ДИАМЕТР» - числовым.
Код имеет следующие входы:
Feature: Функция для анализа
Workspace: Папка, которая будет хранить пару промежуточных таблиц временно
TempTableName1: Имя для одной временной таблицы ,
TempTableName2: Имя для второй временной таблицы
FIELD1 = The неединственное поле
Field2 = поле с числовыми значениями, которые вы хотите, чтобы найти самые низкие из
Код:
# Import modules
from arcpy import *
import os
# Local variables
#Feature to analyze
Feature = r"C:\E1B8\ScriptTesting\Workspace\Workspace.gdb\testfeatureclass"
#Workspace to export table of identicals
Workspace = r"C:\E1B8\ScriptTesting\Workspace"
#Name of temp DBF table file
TempTableName1 = "Table1"
TempTableName2 = "Table2"
#Field names
Field1 = "nMSLINK" #nonunique
Field2 = "DIAMETER" #field with numeric values
#Make layer to allow selection
MakeFeatureLayer_management (Feature, "lyr")
#Path for first temp table
Table = os.path.join (Workspace, TempTableName1)
#Create statistics table with min value
Statistics_analysis (Feature, Table, [[Field2, "MIN"]], [Field1])
#SQL Select rows with frequency not equal to one
sql = '"FREQUENCY" <> 1'
# Path for second temp table
Table2 = os.path.join (Workspace, TempTableName2)
# Select rows with Frequency not equal to one
TableSelect_analysis (Table, Table2, sql)
#Empty list for sql bits
li = []
# Iterate through second table
cursor = da.SearchCursor (Table2, [Field1, "MIN_" + Field2])
for row in cursor:
# Add SQL bit to list
sqlbit = '("' + Field1 + '" = \'' + row[0] + '\' AND "' + Field2 + '" <> ' + str(row[1]) + ")"
li.append (sqlbit)
del row
del cursor
#Create SQL for selection of unwanted features
sql = " OR ".join (li)
print sql
#Select based on SQL
SelectLayerByAttribute_management ("lyr", "", sql)
#Delete selected features
DeleteFeatures_management ("lyr")
#delete temp files
Delete_management ("lyr")
Delete_management (Table)
Delete_management (Table2)
Это должно быть быстрее, чем прямой курсор. Дайте мне знать, если это имеет смысл. Удачи!
Я проверил свой метод с очень большим набором данных, и он был ненадежным. В частности, конечная строка SQL становится слишком большой и вызывает проблемы. Я также тестировал метод andzep, и он работал отлично. Я рекомендую его метод. –
- 1. подсчитанное значение для каждого уникального идентификатора
- 2. Как использовать AWK для уникальной таблицы (сохраняйте самое большое значение для каждого уникального идентификатора)?
- 3. Сохраняйте только минимальное значение для каждого коэффициента.
- 4. Получите максимальное значение столбца для каждого уникального идентификатора
- 5. одна строка для каждого уникального идентификатора клиента/идентификатора партнера
- 6. Объединить значение сгенерированного уникального идентификатора
- 7. Выбор записей с самой последней датой для каждого уникального идентификатора
- 8. SVN - Автоматическое создание уникального идентификатора для каждого файла с версией
- 9. SQL: Получить среднее число записей для каждого уникального идентификатора в пределах другого уникального идентификатора
- 10. Elasticsearch: Фильтр первого документа для каждого уникального идентификатора
- 11. Получение уникального идентификатора для каждого элемента контента NSArrayController в
- 12. Получение уникального идентификатора для UIViewController
- 13. Формулы для создания уникального идентификатора?
- 14. Назначение уникального идентификатора для каждого клиента во время установки
- 15. Подсчитайте количество истекших и непредвиденных строк для каждого уникального идентификатора
- 16. Создание уникального идентификатора для каждого запроса в распределенной системе
- 17. Как извлечь две строки для каждого уникального идентификатора пользователя
- 18. Получить все элементы столбцов для каждого уникального идентификатора в таблице
- 19. R Создать новый фрейм данных для каждого уникального идентификатора
- 20. Создание уникального идентификатора пользователя
- 21. Выберите наименьшее значение в таблице, где наименьшее значение меньше
- 22. Как получить имя столбца уникального идентификатора и уникального значение Mysql
- 23. Генерация идентификатора уникального числа
- 24. Стратегия уникального идентификатора
- 25. Создание уникального идентификатора для разных строк?
- 26. Создание уникального идентификатора для типов классов C++
- 27. Создание уникального идентификатора для цикла
- 28. Написание уникального идентификатора для скрипта?
- 29. уникального идентификатора для записи XML
- 30. запроса для уникального идентификатора с XDocument
Можете ли вы добавить код для минимального примера? – atomh33ls
'# Выберите наименьшее MIDDELLIJN_INWENDIG для каждого MSLINK' ' строк = arcpy.SearchCursor ('Afsluiters_Leidingen', '', '', '', 'MSLINK A; MIDDELLIJN_INWENDIG D') '' для строки в строках: ' \t 'диам = row.MIDDELLIJN_INWENDIG' \t' ДИКТ [row.MSLINK] = diam' 'для ключа в Словаре:' ' \t arcpy.SelectLayerByAttribute_management ('Afsluiters_Leidingen', 'NEW_SELECTION', 'MSLINK =' + ул (key) + 'AND NOT MIDDELLIJN_INWENDIG =' + str (dict [key])) ' \t' arcpy.DeleteFeatures_management ('Afsluiters_Leidingen') ' –
Это работает, но требуется возраст для больших шейп-файлов –