[GIS] QGIS neighborhood analysis

grasspostgispostgresqlqgis

I have a vector shape with many different sized polygons each with an other id and values. I want to assign a new table with Information of each polygon containing the name of the majority (higher proportion) of adjacent polygons attribute name. Ergo some kind of polygon neighborhood analysis.

The query should look to the attribute of each bordering polygon and meassure the length of neighborhood polygon and id.

Does anyone have an idea or a tool how to accomplish this task?

I intend to use QGIS, or postgis. I know there is a tool in arcgis called neighborhood statistic.

Best Answer

This blog post has the answer I think you are looking for.

In this case it looks at neighboring polygons; lists their ids, and sums up a defined attribute of them.
You might want to make a copy of the original data and then run the code in the python console of QGIS.

NOTE:
I noticed an error in his code on line 52 here is the corrected if statement:

    # these conditions. So if a feature is not disjoint, it is a neighbor.
    if (f != intersecting_f and not intersecting_f.geometry().disjoint(geom)):
        neighbors.append(intersecting_f[_NAME_FIELD])
        neighbors_sum += intersecting_f[_SUM_FIELD]

Sample Output: Sample output


#UPDATE#

I've updated to reflect your comment.

If you load the layer into QGIS , edit the variables and output file locations, and run the following, you will get:

  1. A layer for each shared edge
    (showing: id, touches, length, sumcolumn)
  2. A table with a row for each polygon (stats summed)
    (showing: id, length of edges summed, sumcolumn summed)

Sample Output:
1.Shared Edges: 1.shared Edges
2.Sums per polygon:

Sums per polygon

'''
FOR EACH POYGON OF INPUT: 
SUM the length of touching sides
SUM a specified column of touching polygons
'''
import itertools
import math
from PyQt4.QtCore import QVariant

#SPECIFY VARIABLES
polycode = 'ID'
polysum = 'SumCol'
#SPECIFY EPSG
epsg = '28355'
#SPECIFY OUTPUTS
outputedges = r"C://temp//DELETEME//t_line_2.shp"
outputedges_sum = r"C://temp//DELETEME//t_line_2_sum.shp"

#USE TJHE LOADED LAYER:
layer = iface.activeLayer()

#CREATE LINE MEMORY LAYER
vlline = QgsVectorLayer("LineString?crs=EPSG:%s" % epsg, "temporary_lines", "memory")
prline = vlline.dataProvider()
# add fields
prline.addAttributes([QgsField('ID', QVariant.String), QgsField('Touches', QVariant.String), QgsField('length', QVariant.Double), QgsField('tosum', QVariant.Double)])
vlline.updateFields() # tell the vector layer to fetch changes from the provid

#LIST OF EXTERIOR RINGS, ALONG WITH PECIFIED COLUMNS
rings = [(QgsGeometry.fromPolyline(elem.geometry().asPolygon()[0]), elem[polycode], elem[polysum])for elem in layer.getFeatures()]


#CREATE TABLE FOR EACH EDGE (SHOW: id, touches, length, sumcolumn)
for i in  itertools.permutations(rings, 2):
    print 'Working on ID: '+ str(i[0][1])
    if i[0][0].intersects(i[1][0]):
        len = i[0][0].intersection(i[1][0]).length()
        #print len
        fetline = QgsFeature()
        fetline.setGeometry(i[0][0].intersection(i[1][0]))
        fetline.setAttributes([str(i[0][1]),str(i[1][1]),len,(i[1][2])])
        prline.addFeatures([fetline])
        vlline.updateExtents()

#WRITE EDGES TABLES
QgsVectorFileWriter.writeAsVectorFormat(vlline,outputedges,"utf-8",None,"ESRI Shapefile")
iface.addVectorLayer(outputedges, "hello_edges", "ogr")

#CREATE Vlayer of summed data (grouped by ID)
vlayer = QgsVectorLayer( "?query=SELECT ID, SUM(length) sum_length, SUM(tosum) sum_tosum  FROM hello_edges GROUP BY ID ", "vlayer", "virtual" )
querylayer = vlayer.dataProvider()
QgsVectorFileWriter.writeAsVectorFormat(vlayer,outputedges_sum,"utf-8",None,"ESRI Shapefile")
iface.addVectorLayer(outputedges_sum, "hello_sums", "ogr")
iface.showAttributeTable(iface.activeLayer());
Related Question