Суммирование значений соседних полигонов с использованием QGIS?

11

Я надеюсь, что вы можете помочь мне решить следующую проблему: У меня есть векторный (многоугольный) слой. Я хотел бы добавить к слою атрибут, который - для каждого многоугольника - суммирует значения определенного поля всех соседних многоугольников.

Чтобы привести более конкретный пример: у меня есть полигональный слой районов, содержащий информацию о населении. Теперь для каждого района я хотел бы знать, сколько людей живет во всех соседних районах.

Поскольку у меня более 300 районов, я не могу сделать это вручную для каждого района.

Есть ли способ сделать это более эффективно в QGIS?

Alex
источник

Ответы:

8

Такого рода вещи лучше всего делать со Spatialite и SQL.

Сначала вам нужно загрузить ваши данные в базу данных Spatialite, что можно сделать с помощью плагина DBManager, который поставляется с QGIS. Нажмите Импорт Layer/File button.

С вашими данными в базу данных вы можете выполнить следующий запрос с помощью SQLкнопки. Вам просто нужно изменить имена столбцов и таблиц в соответствии с вашими данными.

SELECT COALESCE(SUM(a2.pop),0) as pop_neighbours, 
        a1.pop, 
        a1.name, 
        a1.id, 
        a1.geomm FROM areas a1
LEFT OUTER JOIN areas a2 ON NOT a1.id = a2.id 
                            AND intersects(a2.geomm, a1.geomm)
GROUP BY a1.id

Сообщите инструменту запросов свой уникальный столбец идентификатора (id) и столбец геометрии (geomm), затем просто нажмите «загрузить».

Вы должны иметь что-то вроде этого, как только вы маркируете это, конечно,

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

Распределение запросов

Мы присоединяем слой к себе, используя:

LEFT OUTER JOIN areas a2 ON NOT a1.id = a2.id 
                            AND intersects(a2.geomm, a1.geomm)

но только там, где пересекаются геометрии и идентификаторы не совпадают, в противном случае мы получим одну и ту же запись дважды для каждого многоугольника. Мы также используем LEFT OUTER JOINтак, чтобы мы включали записи, которые не присоединяются, то есть не имеют соседей.

В выделенной части:

SELECT COALESCE(SUM(a2.pop),0) as pop_neighbours, 
            a1.pop, 
            a1.name, 
            a1.id, 
            a1.geomm

мы используем COALESCEдля того, чтобы преобразовать NULLS(без соседей) в 0противном случае они просто остаются NULL.

Тогда мы просто GROUP BY a1.idтак, чтобы мы получили одну запись для каждого многоугольника.

Натан У
источник
Натан, большое спасибо за твой ответ и полезные объяснения. Это сработало даже для абсолютного начинающего и начинающего!
Алекс
+1 Раздел «разбивка запросов» сделан хорошо и очень полезен.
whuber
@ Алекс хорошие вещи. Не забудьте поставить галочку
Натан W
2

Еще один способ сделать это в GRASS (используя панель инструментов GRASS или непосредственно в GRASS). В приведенном ниже примере советник уровня представляет собой векторный слой со странами, а в таблице атрибутов - столбец с населением по стране. Смотрите этот пост для более подробного объяснения.

Шаг 1) Создайте новый слой с таблицей атрибутов, связанной с границами, с двумя столбцами с идентификаторами полигонов, граничащих с линией границы слева и справа соответственно

v.category EA out=EAc layer=2 type=boundary option=add
v.db.addtable EAc layer=2 col="left integer,right integer"
v.to.db EAc option=sides col=left,right layer=2 type=boundary

Шаг 2) Запустите SQL, чтобы создать таблицу, которая связывает идентификаторы стран с суммой населения всех соседних стран:

db.execute sql="CREATE TABLE tmp AS
SELECT ID, sum(pop) as population FROM (
SELECT DISTINCT EAc_2.left as ID, EAc.pop as pop
FROM EAc_2
LEFT JOIN EAc ON EAc_2.right = EAc.cat
WHERE EAc_2.left > -1 AND EAc_2.right > -1
UNION
SELECT DISTINCT EAc_2.right as ID, EAc.pop as pop
FROM EAc_2
LEFT JOIN EAc ON EAc_2.left = EAc.cat
WHERE EAc_2.left > -1 AND EAc_2.right > -1
) GROUP BY ID"

Шаг 3) Соедините новую таблицу tmp с исходной таблицей атрибутов.

v.db.join map=EA@ConsStat layer=1 column=cat otable=tmp ocolumn=ID

Таблица атрибутов вашего векторного слоя теперь должна иметь дополнительный столбец с суммарной совокупностью всех соседних стран.

Ecodiv
источник
2

Отличный ответ @Nathan . Я попытался сделать это, используя pyqgis и shapely. Проверьте этот пост , чтобы загрузить scirpt и запустить его в QGIS. Преимущество этого метода заключается в том, что вы получаете результаты как часть таблицы атрибутов.

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

spatialthoughts
источник