0

I have two polygon layers, layer A and layer B. Layer B polygons are much bigger than layer A polygons. Now, some of the little polygons from layer A are located in the big polygons from layer B, and some are not. And so, for those little polygons from layer A that are located within the big polygons from layer B, some of those little layer A polygons will be located within different big polygons from layer B. That is the setting here.

Each layer A polygon has a unique Object ID. Same with the layer B polygons.

What I want to do is create a new column in the layer A attribute table called "B_ID".

In this column, and so for each layer A polygon/row, I want to enter the object ID of the layer B polygon it is located within. And so let's say Polygons 24 and 55 from layer A are both located within polygon 75 from layer B. Those rows in the layer A attribute table for polygons 24 and 55 would then show a "75" value under the "B_ID" column. And then, if a polygon from layer A happens to not be located within any layer B polygon, then just it would just show a "FALSE" or "N/A" or some rejection-value for that row under the "B_ID" column.

Here is a diagram example of what I am trying to accomplish:

enter image description here

From this I want to produce the following dataframe/table for layer A:

Object_ID     B_ID
------------------------------------
0                ?
1                ?
2                ?
3                ?
...
24              75
...
33             N/A
...
36             N/A
...
41             N/A
...
55              75
56              73  
57              73
58              73
...
61              76
62               ?
63               ?
64               ?
...

And so we see which polygons from layer B the polygons from layer A are located within.

How can this be approached in Python? I am thinking this will need to involve the .intersects() function, but I am confused how to reference location within polygons from a different layer and reference it back to the original layer. I am generally confused how to tell Python what exactly to intersect and how to pull the appropriate object ID from layer B.

2
  • A visual aid of what you're trying to describe in the opening paragraph would go a long way. What do you mean "is located in"? Are you saying that there are small polygons from layer A that are contained in other larger polygons from layer B? Or are you saying that some polygons in layer A are repeated/cloned in layer B?
    – Felipe D.
    Commented Apr 6, 2022 at 21:19
  • 1
    Hello, I just added a visual aid to my post describing the conceptual goal. By "is located in" I am saying that there are small polygons from layer A that are contained within other larger larger polygons from layer B. The polygons from layer A are not repeated/cloned in layer B. Commented Apr 6, 2022 at 21:52

1 Answer 1

1

It seems like you're trying to do a special type of spatial join.

To do that using geopandas, you'd have to do something like this:

import geopandas as gpd

# Suppose the unique ID column for layer_a is called "A_ID"
layer_a = gpd.read_file(...)

# Suppose the unique ID column for layer_b is called "B_ID"
layer_b = gpd.read_file(...)

# Finding the match between layer_a and layer_b
sjoin_results = layer_a.sjoin(layer_b[['B_ID','geometry']], how='left', predicate='within')

The sjoin_results should be a GeoDataFrame that has all of the columns of the original layer_a object with a new column: "B_ID".

9
  • 1
    This looks great and I will try this out! Thank you! So I see this will reproduce the GeoDataFrame for layer_A, but now with the "B_ID" column attached, showing the associated layer B polygon IDs. Though I am a bit confused about the label "A_ID". I don't see "A_ID" in the code, wouldn't the ID of the layer A polygons need to be mentioned in the code somewhere? Commented Apr 6, 2022 at 22:32
  • 1
    Awesome! Happy to help =) Take a look at the commented section in the code. I'm assuming that the A_ID column already belongs in layer_a. I'm also assuming that B_ID already exists in layer_b. If they both already exist in their respective GeoDataFrame objects, the sjoin operation will produce a new GeoDataFrame with all the columns from A (which includes A_ID) and the newly-added B_ID column. I hope that clears things up =)
    – Felipe D.
    Commented Apr 7, 2022 at 0:11
  • Ah ok, I see, so they will be spatially joined by their geometries, and I will then see the matching B_IDs for each A_ID. Awesome! However, as I was so excited to try this out, I encountered this error message: 'ImportError: Spatial indexes require either rtree or pygeos. See installation instructions at geopandas.org/install.html' Are you perhaps familiar with what this might mean? I thought I had installed geopandas and its dependencies just fine, but apparently not. I even tried downloading rtree and pygeos but it did not work. Some issue with .sjoin() I guess. Commented Apr 7, 2022 at 18:46
  • How did you download/install geopandas? Did you, by any chance, install it using Anaconda? If so, you might be able to install rtree using conda install rtree=0.9.3 -c conda-forge. I'm specifying the rtree version because there have been issues with other versions of that library before (see here). If, instead, you want to use pygeos, you can install it using conda install pygeos --channel conda-forge.
    – Felipe D.
    Commented Apr 7, 2022 at 19:43
  • I installed geopandas and its dependencies via pip, including installing rtree before. I am unable to use conda and forge for installations, because every time I try to install with conda, such as using conda install -c conda-forge geopandas, I just get the same Solving environment: failed with initial frozen solve. Retrying with flexible solve. error every time. I do not understand virtual environments well enough to address this issue, and so I simply try to use pip. I successfully installed rtree with pip and then installed geopandas with pip, but I still get the import error. Commented Apr 7, 2022 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.