QGISを使用して隣接ポリゴンの値を合計しますか?


11

次の問題の解決に役立つことを願っています。ベクター(ポリゴン)レイヤーがあります。レイヤーに属性を追加して、すべてのポリゴンについて、そのすべての隣接するポリゴンの特定のフィールドの値を合計します。

より具体的な例を挙げると、人口に関する情報を含む地区のポリゴンレイヤーがあります。さて、すべての地区について、近隣のすべての地区に住んでいる人の数を知りたいと思います。

300以上の地区があるので、各地区ごとにこれを手作業で行うことはできません。

QGISでこれをより効率的に行う方法はありますか?

回答:


8

この種のことは、SpatialiteとSQLを使用するのが最適です。

最初に、QGISに付属のDBManagerプラグインを使用して実行できるSpatialiteデータベースにデータをロードする必要があります。インポートをクリックし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列(id)とジオメトリ列(geomm)を伝え、[ロード]をクリックします。

もちろんラベルを付けたら、このようなものが必要です

ここに画像の説明を入力してください

クエリの内訳

次を使用して、レイヤーをそれ自体に結合しています。

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

ただし、ジオメトリが交差し、IDが同じでない場合のみ、そうでない場合、各ポリゴンに対して同じレコードが2回作成されます。また、aを使用しているLEFT OUTER JOINので、結合しない、つまり隣人のないレコードが含まれます。

選択部分で:

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

(隣人なし)COALESCEをに変換するために使用しています。NULLS0NULL

次にGROUP BY a1.id、ポリゴンごとに1つのレコードを取得するようにします。


ネイサン、あなたの答えと有益な説明に感謝します。完全な空間とSQLの初心者でも機能しました!
アレックス

+1「クエリの内訳」セクションはうまくできており、非常に役立ちます。
whuber

@アレックス良いもの。承認ボタンをチェックすることを忘れないでください。
ネイサンW

2

これを行う別の方法は、GRASS(GRASSツールボックスを使用するか、GRASSで直接)です。次の例では、レイヤーEAは国を含むベクターレイヤーであり、属性テーブルでは国ごとの人口を含む列です。より詳細な説明については、この投稿を参照してください。

手順1)境界にリンクされた属性テーブルを使用して新しいレイヤーを作成します。ポリゴンのIDを持つ2つの列は、それぞれ左右の境界線に接しています

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を実行して、国IDとすべての近隣国の人口の合計をリンクするテーブルを作成します。

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

ベクターレイヤーの属性テーブルには、すべての近隣国の合計人口を含む追加の列があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.