문제 설명
모양이 교차하는 다각형의 수를 어떻게 계산합니까? (How can I count the number of polygons a shape intersects?)
주변에 버퍼가 있는 폴리곤과 포인트가 있는 매우 큰 데이터세트가 있습니다. 포인트의 버퍼가 교차하는 다각형의 수를 포함하는 포인트 데이터에 새 열을 생성하고 싶습니다.
간단한 예는 다음과 같습니다.
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'})
이 데이터는 다음과 같습니다. 내가 하고 싶은 것은 점이 교차하는 다각형의 수를 포함하는 점 데이터 프레임에 다른 열을 만드는 것입니다.
활용해 보았습니다. for 루프는 다음과 같습니다.
points['intersect'] = []
for geo1 in points['geometry']:
for geo2 in df['geometry']:
if geo1.intersects(geo2):
points['intersect'].append('1')
이를 합하여 총 교차 수를 구합니다. 하지만, '값의 길이가 인덱스의 길이와 일치하지 않습니다'라는 오류가 발생합니다. 나는 이것이 단지 2개의 행이 있는 프레임에 3개의 데이터 행을 할당하려고 시도하기 때문이라는 것을 알고 있습니다.
첫 번째 점에 값 2가 할당되고 두 번째 점에 값이 할당되도록 어떻게 카운트를 집계할 수 있습니까? 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)
(by tom91、martinfleis)