# Calculate polygon field based on neigboring polygon attribute

I have a vector shape with many different sized polygons each possessing an own class name (for instance "houses", "houses with offices", etc ...)

I want to assign a new field to 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 change another fields value to the name which occurs the most. For instance the beige polygon in the middle of the above image is surrounded by polygons with the attribute "houses" and therefore it should get the attribute "houses". (Best would be if i can somehow display and save the proportion of different attributed polygons).

Does anyone have an idea or a tool how to accomplish this task? I am thankful for every partial or full solution. Any good way to solve this problem is appreciated!

I intend to use QGIS, but i can also switch to other tools (Arcgis 9, Grass, Saga, R, ...)

-
ArcGIS 9.1 is a Retired version so I removed its tag from this question. – PolyGeo Apr 25 '13 at 10:16

Quantum GIS has excellent support for PostGIS (which I guess you can use at home since it's free software), so if you are familiar with it, you could script this procedure using SQL with something like this:

``````UPDATE poly_layer p
SET neighbors_class = (
SELECT class FROM (
SELECT class, count(0)
FROM poly_layer n
WHERE ST_Intersects(n.geom, p.geom)
GROUP BY class
ORDER BY count(0) DESC
) AS foo LIMIT 1
);
``````

(more or less :) )

-
Hey, thanks for the bounty award! As I haven't tested this, it will need some modifications to work for you, I would be very interested in seeing them. – kprist Nov 23 '12 at 11:06

I have a solution. Not necessarily pretty but it works on my test dataset and is actually fairly easy.

First up, this only works if your "houses" and "office" categorisation is numerical because you can't calculate a mode (what you want) from non-numerical data in ArcGIS. That should be easy enough to arrange so I'll leave it as an exercise for the reader.

ArcGIS, in the toolbox go to: `Analysis Tools -> Overlay -> *Spatial Join*` Both the target and the join features should be the same dataset (assuming you're comparing against the same dataset, I inferred you were).

You then need to do some Field Map magic. Click the black "+" icon. Create a new field like this:

Actually you'll want to use mode I think rather than median which is used in this screenshot.

When its been added, you right-click on the entry in the field map window and click Add Input Field. This brings up the below.

This is the field that you want averaged into Mode. In this case, it's a field called **num. You'll note each field appears twice, this is because we're using the same input as target and joinee. The bottom set is the joinee and thus the set you want, as I've selected here.

You'll end up with something looking like this:

For the purposes of my example, I've deleted the other columns/fields from the output field map to keep things simple.

This works for me creating a new dataset which contains the numerical mode value of its surrounding polgyons (which Intersects it).

-
great, thanks! I could build an index value for categorical names, therefore this shouldn't be a problem. I will try your solution tomorrow and report back! – Curlew Nov 12 '12 at 16:10
Welcome. I've added "arcgis" as a tag as there's an answer that reflects it. Hopefully one of the QGIS types can show how to do it in that as I'd be interested to see those analysis tools. – GIS-Jonathan Nov 12 '12 at 16:15
ahh, damn. Sry, but your solution doesn't work for me. I only have ArcGis 9.1 which doesn't possess the spatial join method in the Analyst toolbox. All i can do is a simply Union. I didn't know that as i usually work with QGIS, GRASS – Curlew Nov 13 '12 at 9:23
@Curlew Hmm. It was definitely in 9.2 (webhelp.esri.com/arcgisdesktop/9.2/…) and this document (support.esri.com/en/knowledgebase/techarticles/detail/37544) implies it should even exist in 9.0 ---- Ok, this page - giscadblog.blogspot.co.uk/2006/10/… suggests its new in 9.2, but that you could maybe use the NEAR tool in 9.1 – GIS-Jonathan Nov 13 '12 at 10:53

Try nearest neighbor analysis in Arcmap toolbox. Conceptually have the linear bounding of polygons named as to the polygon name with internal edges taking on name, kind of like side addressing or direction, object oriented model, with ascii edges showing direction of enclosure. Then run various intersection and edge analysis. Generate polygon centroids with names from neighbor analysis. Use masking filters based on distance to filter, mask, merge, or exclude unwanted results.

Maybe build a python builder model in Arcmap toolbox to create your work flow.

-
thanks, but there is already an ArcGis solution. On my homesystem i can only use QGIS, which is why i am especially interested in an example. – Curlew Nov 19 '12 at 22:34

@ GIS_Jonathan:

I don't know of a tool or plugin that you could use off-the-shelf, but you could easily write one in Python using OGR.

You need to loop for each polygon. Then select all polygons that meet your neighbourhood criteria. Unfortunately Curlew's is misleading in this regard because I am left wondering why some neighbouring polygons are not counted and some polygons that are close but clearly not direct neighbours are included. If we go with his statement of 'bordering' polygons rather than the image, then the solution is simple to achieve with standard spatial queries.

With your selection, create a list of values for the attribute of interest. Then pass the list to a function to determine the most common member in that list (see an example here). Write that value to the current feature's 'neighbourhood attribute'.

Rinse and repeat until EOF.

If you've used OGR and Python before then this solution should be fairly straightforward. You could achieve a similar thing in PostGIS but I'm better at Python than SQL so this is just how I'd do it.

-
thanks for clarification. I certainly thought about coding a script, maybe i will give it a go. The dataset from which the image originates consist of many houses which have the wrong attribute. Normally all neighbouring polygons should count. This however results in some wrong reclassification, which is maybe what you mean. I thought of solving that dilemma by making a subset of the vector layer first. – Curlew Nov 19 '12 at 21:58