Как повысить производительность при использовании курсоров ArcGIS в Python с большими таблицами?

10

У меня есть довольно большой класс точечных объектов в файловой базе геоданных (~ 4 000 000 записей). Это регулярная сетка точек с разрешением 100 м.

Мне нужно выполнить своего рода обобщение на этом слое. Для этого я создаю новую сетку, где каждая точка находится в середине 4 «старых» точек:

 *     *     *     *
    o     o     o
 *     *     *     *
    o     o     o
 *     *     *     *

[*] = точка исходной сетки - [o] = точка новой сетки

Значение атрибута каждой новой точки рассчитывается на основе взвешенных значений ее 4-х соседей в старой сетке. Таким образом, я зацикливаюсь на всех точках моей новой сетки и для каждой из них я зацикливаюсь на всех точках моей старой сетки, чтобы найти соседей (сравнивая значения X и Y в таблице атрибутов). Как только 4 соседа были найдены, мы выходим из цикла.

Здесь нет методологической сложности, но моя проблема в том, что, основываясь на моих первых тестах, этот сценарий будет длиться недели, чтобы завершиться ...

Видите ли вы возможность сделать его более эффективным? Несколько идей на моей голове:

  • Индексируйте поля X и Y => Я сделал это, но не заметил значительного изменения производительности
  • Сделайте пространственный запрос, чтобы найти соседей, а не на основе атрибутов. Это действительно поможет? Какая пространственная функция в ArcGIS должна выполнять эту работу? Я сомневаюсь, что, например, буферизация каждой новой точки окажется более эффективной
  • Преобразуйте класс пространственных объектов в массив NumPy. Это поможет? До сих пор я мало работал с NumPy, и я не хотел бы углубляться в это, если кто-то не скажет мне, что это действительно может помочь сократить время обработки
  • Что-нибудь еще?
Стефан Генриод
источник
Какую версию Arcmap вы используете?
Мартин
Рассматривали ли вы PostGIS? Это вариант?
Чед Купер
Извините, что я забыл, что: ArcGIS 10.1 // Python 2.7
Стефан Генриод
Нет, PostGIS, к сожалению, не вариант, мои руки, к сожалению, здесь довольно
тесно

Ответы:

13

Что делать, если вы подали точки в массив numpy и использовали scipy cKDTree для поиска соседей. Используя эту технику, я обрабатываю облака точек LiDAR с большим количеством точек (> 20 миллионов) за несколько МИНУТ. Существует документация здесь для kdtree и здесь для Numpy преобразования. По сути, вы читаете x, y в массив и перебираете каждую точку массива, находя индексы точек на определенном расстоянии (окрестности) каждой точки. Вы можете использовать эти индексы для вычисления других атрибутов.

Barbarossa
источник
этот ответ лучше моего
radouxju
Мне нравится эта идея, но у меня нет scipy на рабочей станции, на которой я работаю (и нет прав администратора). Если мне удастся установить этот пакет, я попробую
Стефан Генриод
4

Я с Barbarossa ... arcpy курсоры безумно хромают, поэтому я использую их только для того, чтобы пройти таблицу или класс пространственных объектов ровно один раз. Если я не могу выполнить работу за один цикл, я использую курсор, чтобы заполнить какую-то другую структуру данных и работать с ней.

Если вы не хотите суетиться с Numpy, просто создайте простой словарь Python, в котором вы используете свои координаты в качестве простого текстового ключа, и укажите атрибуты, необходимые для расчета, в список в качестве значения элемента словаря.

На втором этапе вы можете легко получить значения, необходимые для вычисления точки, просто получив их из своего словаря (что невероятно быстро из-за словарей hashindex элементов).

Юрген Цорниг
источник
Мне действительно нравится ваша идея со словарями, и я только что реализовал ее. Это действительно работает намного лучше ... пока я не напишу результаты с помощью row.insertRow () ... Есть идеи, как я могу улучшить эту часть?
Стефан Генриод
У меня была похожая проблема, когда мне нужно было выбрать около 10.000 баллов из 14 млн. а затем удалите его. arcpy.cursors, где можно удалить только 1 или 2 точки в секунду (!). поэтому я установил модуль pyodbc, чтобы удалить их одним оператором SQL DELETE всего за одну секунду. ОБНОВЛЕНИЕ поверх SQL принесет вам много улучшений, если вы только хотите изменить атрибуты ... тем не менее, вам придется устанавливать дополнительные модули Python ... но это того стоит.
Юрген Цорниг
2

Для обычной сетки гораздо эффективнее работать в растровом формате. Преобразовав свою первую сетку в растр, вы можете выполнить повторную выборку с тем же разрешением, используя билинейный интерполятор, но сместив ваше выходное изображение на 1/2 пикселя по осям X и Y, и снова вернитесь к точкам, если вам все еще нужны точки.

РЕДАКТИРОВАТЬ: для сложных правил принятия решений вы можете преобразовать каждое из необходимых полей в новую растровую полосу, затем сделать четыре копии этих полос и сдвинуть растр в 4 направлениях на 1/2 пикселя (+50, - 50), (+ 50, + 50), (-50, -50) и (-50, + 50). Тогда вы можете использовать регулярную карту алгебры

radouxju
источник
Спасибо. Я действительно подумал об этом решении, но я не уверен, смогу ли я / как реализовать вычисление нового значения в растровом формате. Позвольте мне объяснить: для каждой новой точки (или новой растровой ячейки) мне нужно рассчитать ее значение следующим образом: я беру значение каждого из ее соседей. У каждого из этих значений есть вероятность присвоения нового значения конкретному значению. Например, если у одного соседа есть значение 202, то оно даст значение 3 (с весом 1) или значение 11 (с весом 5). Затем мы суммируем все 4 соседа и находим новое значение ... Не уверен, что это очень ясно ...
Стефан Генриод
PS: расчет, чтобы найти новое значение, может в некоторых случаях основываться на 2 атрибутах, а не только на одном, который может отбросить подход
Растра
для вашей взвешенной суммы вам просто нужны два растра: один, где вы пересчитываете произведение весов и значений, второй, где вы переопределяете только веса. Если вы разделите первое на второе, вы получите взвешенную сумму.
Радучжу
1
@ StéphaneHenriod - в качестве предложения вы можете рассмотреть вопрос об изменении вопроса, чтобы добавить эти дополнительные спецификации. Учитывая начальный вопрос, я думаю, что этот ответ имеет огромное значение, но с этой новой информацией ответ Барбароссы выглядит хорошо.
Никсан
2

Спасибо всем за вашу помощь!

В конце концов я нашел очень непитонический способ решения этой проблемы ... Что на самом деле занимало больше всего компьютерного времени, так это найти 4 соседей в каждой точке. Вместо того, чтобы использовать атрибуты X и Y (либо с дугообразным курсором, либо внутри другой структуры данных, например, python ditionary), я в итоге использовал инструмент ArcGIS Generate near table . Я предполагаю, что это использует пространственные индексы, и производительность, очевидно, намного выше, без необходимости самому внедрять индекс.

Стефан Генриод
источник
0

Проблема с курсорами заключается в том, что вы можете перемещаться по ним только одним способом и не можете вернуться назад. Хотя это и не рекомендуется, вы можете заполнить феодоры структурой, если вы планируете вернуться к ним.

Если вы смогли обработать свои функции за один цикл, я предлагаю включить утилизацию. Это параметр в вашей функции поиска классов объектов, который позволяет Python повторно использовать память, выделенную старыми объектами, и значительно ускоряет обход объектов в курсоре. Вы можете обработать свою сетку на 80% быстрее.

Проблема в том, что вы не можете включить утилизацию, если планируете сохранять полученные функции из курсора.

hnasr
источник
Я хочу исследовать эту тему "Переместить курсор", но не могу найти документацию по справке ESRI. У вас есть ссылка? Курсор поиска не имеет параметра перезапуска. Атрибут select_by_Attribute не имеет такого параметра. Я ничего не вижу в ENV.
Klewis
Я написал статью некоторое время назад husseinnasser.com/2009/08/when-to-use-recycling-cursor.html?m=1
hnasr
1
Я не думаю, что «повторное использование курсоров» доступно через ArcPy, только с основными Arcobjects.
Klewis