Podsumowując wartości sąsiednich wielokątów za pomocą QGIS?


11

Mam nadzieję, że możesz mi pomóc z następującym problemem: Mam warstwę wektorową (wielokąta). Chciałbym dodać atrybut do warstwy, która - dla każdego wielokąta - sumuje wartości określonego pola wszystkich sąsiednich wielokątów.

Podam bardziej konkretny przykład: mam wieloboczną warstwę dzielnic zawierającą informacje o ludności. Teraz dla każdej dzielnicy chciałbym wiedzieć, ile osób mieszka we wszystkich sąsiednich dzielnicach.

Ponieważ mam ponad 300 dzielnic, nie mogę tego zrobić ręcznie dla każdej dzielnicy.

Czy jest jakiś sposób, aby zrobić to bardziej efektywnie w QGIS?

Odpowiedzi:


8

Tego rodzaju czynności najlepiej wykonywać w Spatialite i SQL.

Najpierw musisz załadować swoje dane do bazy danych Spatialite, co może odbywać się za pomocą wtyczki DBManager dostarczanej z QGIS. Kliknij przycisk Importuj Layer/File button.

Z danymi w bazie danych możesz następnie uruchomić następujące zapytanie za pomocą SQLprzycisku. Musisz tylko zmienić nazwy kolumn i tabel, aby pasowały do ​​twoich danych.

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

Poinformuj narzędzie do wysyłania zapytań o swojej unikalnej kolumnie identyfikatora (id) i kolumnie geometrii (geomm), a następnie po prostu kliknij wczytaj.

Powinieneś mieć coś takiego, jak tylko to oznaczysz

wprowadź opis zdjęcia tutaj

Podział zapytania

Łączymy warstwę ze sobą za pomocą:

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

ale tylko tam, gdzie przecinają się geometrie, a identyfikatory nie są takie same, w przeciwnym razie otrzymamy ten sam rekord dwa razy dla każdego wielokąta. Używamy również LEFT OUTER JOINtak, aby uwzględnić rekordy, które się nie dołączają, tj. Nie mają sąsiadów.

W wybranej części:

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

używamy COALESCE, aby przekonwertować NULLS(bez sąsiadów) na 0inny, po prostu pozostaną NULL.

Następnie robimy to tylko po GROUP BY a1.idto, aby uzyskać pojedynczy rekord dla każdego wielokąta.


Nathan, wielkie dzięki za odpowiedź i pomocne wyjaśnienia. Działa nawet dla całkowicie początkujących i przestrzennych!
Alex

+1 Sekcja „podział zapytań” jest ładnie wykonana i bardzo pomocna.
whuber

@Alex dobre rzeczy. Nie zapomnij zaznaczyć przycisku akceptuj.
Nathan W

2

Innym sposobem na to jest GRASS (za pomocą przybornika GRASS lub bezpośrednio w GRASS). W poniższym przykładzie warstwa EA jest warstwą wektorową z krajami, aw tabeli atrybutów kolumną z liczbą ludności według krajów. Zobacz ten post, aby uzyskać bardziej szczegółowe wyjaśnienie.

Krok 1) Utwórz nową warstwę z tabelą atrybutów połączoną z granicami, z dwiema kolumnami o identyfikatorach wielokątów graniczących odpowiednio z linią graniczną po lewej i prawej stronie

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

Krok 2) Uruchom instrukcję SQL, aby utworzyć tabelę, która łączy identyfikatory kraju z sumą populacji wszystkich sąsiednich krajów:

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"

Krok 3) Dołącz do nowej tabeli tmp z oryginalną tabelą atrybutów.

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

Tabela atrybutów warstwy wektorowej powinna teraz zawierać dodatkową kolumnę ze zsumowaną populacją wszystkich sąsiednich krajów.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.