# Calculating final polygon after subtracting all intersecting polygons using shapely [closed]

I have a list of centroids that I buffer to 5000 meters radius. I need to take each resulting circle and run it against the remaining centroids(also buffered to 5000 m) and find the final shape after subtracting all intersections.

In other words, I need the circle shape A to iterate over the dataset, find all circle shape(s) that intersect with it (B and C) and then create a column with a geocoordinates of the polygon, that is resulting after all intersecting circle areas are subtracted (see image below) and if it does not intersect with any other cirlce(s), just add a geocoordinate for the entire circle: Here is the code I have:

``````df.head()

# Output:
#                cell_centroid  pop     id
#0  POINT(21.25602 55.903539)   9004.0  0
#1  POINT(21.119156 55.538406)  517.0   1
#2  POINT(21.249535 55.890204)  10369.0 2
#3  POINT(21.359934 55.904164)  800.0   3
#4  POINT(24.433042 56.104589)

for i, r in df.iterrows():
# take the centroid of interest and buffer it with a 5000 meter radius
a = gpd.GeoSeries(r['cell_centroid'], crs = 4326).to_crs(crs = 3857).buffer(5000)
# separate that centroid from df and save the remaining rows as a separate df
df_dropped = df.drop(i, axis = 0)
li = [] # an empty list to collect intersections
# iterate over the separated df to find if the dropped centroid intersects with any of the remaining in the dataset

for j, s in df_dropped.iterrows():
# the centroid to be compared with
b = gpd.GeoSeries(s['cell_centroid'], crs = 4326).to_crs(crs = 3857).buffer(5000)

# check if the centroid1 intersects with centroid2
if(a.intersects(b) == True):
tf = a.intersects(b)
# add the intersects to the list
li.append(tf)
# create a list of just the True shapes(shapes with which the input shape intersects), using intersects list as an index
new_df = df_dropped.loc[np.array(li)]

if len(new_df) > 0:
print('iteration {} : \n{}'.format(i, new_df))
else:
print('iteration {} is empty'.format(i))

# iterate through True shapes dataset (new_df) and find the difference between input shape and each shape in the new_df.
if len(new_df) > 1:
iterator = 1
for k, t in new_df.iterrows():
c = gpd.GeoSeries(t['cell_centroid'], crs = 4326).to_crs(crs=3857).buffer(5000)
tf = a.difference(c)
col_name = 'intersect' + str(iterator)
df.loc[:, col_name] = tf
iterator += 1
# for each centroid a, put each True value into a separate new column in the orginal dataset
elif len(new_df) == 1:
c = gpd.GeoSeries(t['cell_centroid'], crs = 4326).to_crs(crs=3857).buffer(5000)
tf = a.difference(c)
# for each centroid a, put each True value into a separate new column in the orginal dataset
df['intersect1'] = tf
else:
continue

``````

The error I am getting is:

``````  ---> 34         c = gpd.GeoSeries(t['cell_centroid'], crs = 4326).to_crs(crs=3857).buffer(5000)
35         tf = a.difference(c)
36         # for each centroid a, put each True value into a separate new column in the orginal dataset

NameError: name 't' is not defined
``````

My questions are:

1. Is this the most optimal way to calculate final shape (less all intersects) for a each buffered centroid?

2. Why am I getting an error on line 34? t is defined at the beginning of the loop.

UPDATE:

I have changed the code as suggested in the answer:

``````df['cell_centroid'] = df['cell_centroid'].apply(wkt.loads)

gdf = gpd.GeoDataFrame(df, geometry="cell_centroid", crs = 4326).to_crs(crs=3857)

gdf["buffer"] = gdf.buffer(5000)
gdf["difference"] = None

gdf = gdf.set_geometry("buffer")

for i, row in gdf.iterrows():
others = gdf[gdf["id"] != row["id"]]
gdf.loc[i, "difference"] = diff

gdf = gdf.set_geometry("difference")
``````

The error I am getting now is:

``````---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
4 #    gdf.loc[i, "difference"] = gpd.GeoSeries(diff)
----> 5     gdf.loc[i, "difference"] = diff
...

ValueError: Must have equal len keys and value when setting with an iterable'
``````
• @KadirŞahbaz done, thank you Jan 6 at 20:49
• @KadirŞahbaz fixed, my apologies. Jan 6 at 21:04
• Could you add a sample image representing what exactly you try to achieve. I read your question for a while, I cannot understand. I have not encountered the error you mentioned yet, because I get different errors before that line. Jan 6 at 21:35
• @KadirŞahbaz done. Let me know if this makes sense Jan 6 at 21:59

In the case of `len(new_df) == 1`, since `t` is not defined in `elif`, you get the error. That means the first block of `if` never runs before you get the error. Even if the first block worked once, you would get the wrong result after all. Because `t` would be `t` coming from previous iteration, not from current iteration.

In case of `len(new_df) > 1`, first block of `if` statement processes. Since `t` is defined by `for` loop, you won't get an error for the first block of `if`.

To get rid of that error, add `t = new_df.iloc` under `elif` before `c = gpd...`. You may encounter different errors though.

The more optimal script:

``````df['cell_centroid'] = df['cell_centroid'].apply(wkt.loads)

gdf = gpd.GeoDataFrame(df, geometry="cell_centroid", crs = 4326).to_crs(crs=3857)

gdf["buffer"] = gdf.buffer(5000)
gdf["difference"] = None

gdf = gdf.set_geometry("buffer")

for i, row in gdf.iterrows():
others = gdf[gdf["id"] != row["id"]] 