How can I count the number of polygons a shape int

2020-02-15 05:51发布

问题:

I have a very large dataset with a polygons and points with buffers around them. I would like to creat a new column in the points data which includes the number of polygons that point's buffer intersects.

Heres a simplified example:

import pandas as pd
import geopandas as gp
from shapely.geometry import Polygon
from shapely.geometry import Point
import matplotlib.pyplot as plt

## Create polygons and points ##

df = gp.GeoDataFrame([['a',Polygon([(1, 0), (1, 1), (2,2), (1,2)])],
                     ['b',Polygon([(1, 0.25), (2,1.25), (3,0.25)])]],
                     columns = ['name','geometry'])
df = gp.GeoDataFrame(df, geometry = 'geometry')

points = gp.GeoDataFrame( [['box', Point(1.5, 1.115), 4],
                        ['triangle', Point(2.5,1.25), 8]],
                     columns=['name', 'geometry', 'value'], 
                     geometry='geometry')

##Set a buffer around the points##

buf = points.buffer(0.5)
points['buffer'] = buf
points = points.drop(['geometry'], axis = 1) 
points = points.rename(columns = {'buffer': 'geometry'})

This data looks like this: What I'd like to do is create another column in the points dataframe that includes the number of polygons that point intersects.

I've tried utilising a for loop as such:

points['intersect'] = []
for geo1 in points['geometry']:
    for geo2 in df['geometry']:
        if geo1.intersects(geo2):
            points['intersect'].append('1')

Which I would then sum to get the total number of intersects. However, I get the error: 'Length of values does not match length of index'. I know this is because it is attempting to assign three rows of data to a frame with only two rows.

How can I aggrigate the counts so the first point is assigned a value of 2 and the second a value of 1?

回答1:

If you have large dataset, I would go for solution using rtree spatial index, something like this.

import pandas as pd
import geopandas as gp
from shapely.geometry import Polygon
from shapely.geometry import Point
import matplotlib.pyplot as plt

## Create polygons and points ##

df = gp.GeoDataFrame([['a',Polygon([(1, 0), (1, 1), (2,2), (1,2)])],
                     ['b',Polygon([(1, 0.25), (2,1.25), (3,0.25)])]],
                     columns = ['name','geometry'])
df = gp.GeoDataFrame(df, geometry = 'geometry')

points = gp.GeoDataFrame( [['box', Point(1.5, 1.115), 4],
                        ['triangle', Point(2.5,1.25), 8]],
                     columns=['name', 'geometry', 'value'], 
                     geometry='geometry')

# generate spatial index
sindex = df.sindex
# define empty list for results
results_list = []
# iterate over the points
for index, row in points.iterrows():
    buffer = row['geometry'].buffer(0.5)  # buffer
    # find approximate matches with r-tree, then precise matches from those approximate ones
    possible_matches_index = list(sindex.intersection(buffer.bounds))
    possible_matches = df.iloc[possible_matches_index]
    precise_matches = possible_matches[possible_matches.intersects(buffer)]
    results_list.append(len(precise_matches))
# add list of results as a new column
points['polygons'] = pd.Series(results_list)