Saya punya 2 geodataframe:
import geopandas as gpd
from shapely.geometry import Point
gpd1 = gpd.GeoDataFrame([['John',1,Point(1,1)],['Smith',1,Point(2,2)],['Soap',1,Point(0,2)]],columns=['Name','ID','geometry'])
gpd2 = gpd.GeoDataFrame([['Work',Point(0,1.1)],['Shops',Point(2.5,2)],['Home',Point(1,1.1)]],columns=['Place','geometry'])
dan saya ingin mencari nama titik terdekat di gpd2 untuk setiap baris di gpd1:
desired_output =
Name ID geometry Nearest
0 John 1 POINT (1 1) Home
1 Smith 1 POINT (2 2) Shops
2 Soap 1 POINT (0 2) Work
Saya sudah mencoba membuatnya berfungsi menggunakan fungsi lambda:
gpd1['Nearest'] = gpd1.apply(lambda row: min_dist(row.geometry,gpd2)['Place'] , axis=1)
dengan
def min_dist(point, gpd2):
geoseries = some_function()
return geoseries
Jawaban:
Anda bisa langsung menggunakan fungsi Shapely Poin terdekat (geometri GeoSeries adalah geometri Shapely):
Penjelasan
sumber
sample_point = gpd2.geometry.unary_union[400] /
sample_point in gpd2.geometry
Ini mengembalikan True.gpd2.geometry == sample_point
Ini keluar semua False.gpd2.geometry.geom_equals(sample_point)
berfungsi.Jika Anda memiliki kerangka data yang besar, saya telah menemukan bahwa metode
scipy
indeks spasial cKDTree.query
mengembalikan hasil yang sangat cepat untuk pencarian tetangga terdekat. Karena menggunakan indeks spasial, urutan besarnya lebih cepat daripada perulangan melalui dataframe dan kemudian menemukan minimum semua jarak. Ini juga lebih cepat daripada menggunakan shapely'snearest_points
dengan RTree (metode indeks spasial tersedia melalui geopanda) karena cKDTree memungkinkan Anda untuk membuat vektor pencarian Anda, sedangkan metode lainnya tidak.Berikut adalah fungsi pembantu yang akan mengembalikan jarak dan 'Nama' tetangga terdekat di
gpd2
dari setiap titik digpd1
. Ini mengasumsikan kedua gdf memilikigeometry
kolom (poin).Dan jika Anda ingin menemukan titik terdekat ke LineString, berikut ini contoh kerjanya:
sumber
Menemukannya:
Tentu saja ada kritik. Saya bukan penggemar menghitung ulang gpd2 ['Dist'] untuk setiap baris gpd1 ...
sumber
Jawaban oleh Gene tidak berhasil untuk saya. Akhirnya saya menemukan bahwa gpd2.geometry.unary_union menghasilkan geometri yang hanya berisi sekitar 30.000 dari total sekitar 150.000 poin. Untuk orang lain yang mengalami masalah yang sama, inilah cara saya menyelesaikannya:
sumber
Bagi siapa pun yang memiliki kesalahan pengindeksan dengan data mereka sendiri saat menggunakan jawaban yang sangat baik dari @ JHuw , masalah saya adalah bahwa indeks saya tidak selaras. Menyetel ulang indeks gdfA dan gdfB memecahkan masalah saya, mungkin ini dapat membantu Anda juga @ Shakedk .
sumber