У меня есть большой набор данных (O (10 ^ 6) строк) (точки со значениями), где мне нужно сделать следующее для всех точек:
- Найдите 3 ближайшие точки в пределах заданного радиуса.
- Вычислите среднее значение, связанное с этими тремя точками.
- Сохраните это среднее значение до точки, на которую я смотрю
«Невекторизованный» подход состоял бы в том, чтобы просто перебрать все точки ... для всех точек, а затем применить логику. Однако это плохо масштабируется.
Я включил игрушечный пример, который делает то, что я хочу. Из идей, которые я уже рассмотрел, следующие:
- using shapely.ops.nearest_points: это, однако, похоже, возвращает только одну ближайшую точку.
- буферизация вокруг каждой отдельной точки и создание соединения с исходным GeoDataframe: похоже, что он будет масштабироваться даже хуже, чем наивный подход.
Вот игрушечный пример логики, которую я хочу реализовать:
import pandas as pd
import numpy as np
from shapely.wkt import loads
import geopandas as gp
points=[
'POINT (1 1.1)', 'POINT (1 1.9)', 'POINT (1 3.1)',
'POINT (2 1)', 'POINT (2 2.1)', 'POINT (2 2.9)',
'POINT (3 0.8)', 'POINT (3 2)', 'POINT (3 3)'
]
values=[9,8,7,6,5,4,3,2,1]
df=pd.DataFrame({'points':points,'values':values})
gdf=gp.GeoDataFrame(df,geometry=[loads(x) for x in df.points], crs={'init': 'epsg:' + str(25832)})
for index,row in gdf.iterrows(): # Looping over all points
gdf['dist'] = np.nan
for index2,row2 in gdf.iterrows(): # Looping over all the other points
if index==index2: continue
d=row['geometry'].distance(row2['geometry']) # Calculate distance
if d<3: gdf.at[index2,'dist']=d # If within cutoff: Store
else: gdf.at[index2,'dist']=np.nan # Otherwise, be paranoid and leave NAN
# Calculating mean of values for the 3 nearest points and storing
gdf.at[index,'mean']=np.mean(gdf.sort_values('dist').head(3)['values'].tolist())
print(gdf)
Результирующий GeoDataframe находится здесь:
points values geometry dist mean
0 POINT (1 1.1) 9 POINT (1 1.1) 2.758623 6.333333
1 POINT (1 1.9) 8 POINT (1 1.9) 2.282542 7.000000
2 POINT (1 3.1) 7 POINT (1 3.1) 2.002498 5.666667
3 POINT (2 1) 6 POINT (2 1) 2.236068 5.666667
4 POINT (2 2.1) 5 POINT (2 2.1) 1.345362 4.666667
5 POINT (2 2.9) 4 POINT (2 2.9) 1.004988 4.333333
6 POINT (3 0.8) 3 POINT (3 0.8) 2.200000 4.333333
7 POINT (3 2) 2 POINT (3 2) 1.000000 3.000000
8 POINT (3 3) 1 POINT (3 3) NaN 3.666667
Вы можете увидеть состояние последней итерации.
- Все дистанции были рассчитаны без учета итогового места, которое осталось за НАН.
- Среднее значение последней итерации - это среднее значение трех ближайших точек: 2, 4 и 5, а именно 3,666667.
Как мне сделать это более масштабируемым образом?