Ini adalah geodatframe pertama saya:
!pip install geopandas
import pandas as pd
import geopandas
city1 = [{'City':"Buenos Aires","Country":"Argentina","Latitude":-34.58,"Longitude":-58.66},
{'City':"Brasilia","Country":"Brazil","Latitude":-15.78 ,"Longitude":-70.66},
{'City':"Santiago","Country":"Chile ","Latitude":-33.45 ,"Longitude":-70.66 }]
city2 = [{'City':"Bogota","Country":"Colombia ","Latitude":4.60 ,"Longitude":-74.08},
{'City':"Caracas","Country":"Venezuela","Latitude":10.48 ,"Longitude":-66.86}]
city1df = pd.DataFrame(city1)
city2df = pd.DataFrame(city2)
gcity1df = geopandas.GeoDataFrame(
city1df, geometry=geopandas.points_from_xy(city1df.Longitude, city1df.Latitude))
gcity2df = geopandas.GeoDataFrame(
city2df, geometry=geopandas.points_from_xy(city2df.Longitude, city2df.Latitude))
City1
City Country Latitude Longitude geometry
0 Buenos Aires Argentina -34.58 -58.66 POINT (-58.66000 -34.58000)
1 Brasilia Brazil -15.78 -47.91 POINT (-47.91000 -15.78000)
2 Santiago Chile -33.45 -70.66 POINT (-70.66000 -33.45000)
dan geodataframe kedua saya: City2:
City Country Latitude Longitude geometry
1 Bogota Colombia 4.60 -74.08 POINT (-74.08000 4.60000)
2 Caracas Venezuela 10.48 -66.86 POINT (-66.86000 10.48000)
Saya ingin frame data ketiga dengan kota terdekat dari city1 ke city2 dengan jarak seperti:
City Country Latitude Longitude geometry Nearest Distance
0 Buenos Aires Argentina -34.58 -58.66 POINT (-58.66000 -34.58000) Bogota 111 Km
Inilah solusi aktual saya menggunakan geodjango dan dict (tapi terlalu lama):
from django.contrib.gis.geos import GEOSGeometry
result = []
dict_result = {}
for city01 in city1 :
dist = 99999999
pnt = GEOSGeometry('SRID=4326;POINT( '+str(city01["Latitude"])+' '+str(city01['Longitude'])+')')
for city02 in city2:
pnt2 = GEOSGeometry('SRID=4326;POINT('+str(city02['Latitude'])+' '+str(city02['Longitude'])+')')
distance_test = pnt.distance(pnt2) * 100
if distance_test < dist :
dist = distance_test
result.append(dist)
dict_result[city01['City']] = city02['City']
Inilah beberapa percobaan saya:
from shapely.ops import nearest_points
# unary union of the gpd2 geomtries
pts3 = gcity2df.geometry.unary_union
def Euclidean_Dist(df1, df2, cols=['x_coord','y_coord']):
return np.linalg.norm(df1[cols].values - df2[cols].values,
axis=1)
def near(point, pts=pts3):
# find the nearest point and return the corresponding Place value
nearest = gcity2df.geometry == nearest_points(point, pts)[1]
return gcity2df[nearest].City
gcity1df['Nearest'] = gcity1df.apply(lambda row: near(row.geometry), axis=1)
gcity1df
di sini:
City Country Latitude Longitude geometry Nearest
0 Buenos Aires Argentina -34.58 -58.66 POINT (-58.66000 -34.58000) Bogota
1 Brasilia Brazil -15.78 -70.66 POINT (-70.66000 -15.78000) Bogota
2 Santiago Chile -33.45 -70.66 POINT (-70.66000 -33.45000) Bogota
Salam
Jawaban:
Pertama, saya menggabungkan dua frame data dengan cross join. Dan kemudian, saya menemukan jarak antara dua titik menggunakan
map
python. Saya menggunakanmap
, karena sebagian besar waktu itu jauh lebih cepat daripadaapply
,itertuples
,iterrows
dll (Referensi: https://stackoverflow.com/a/52674448/8205554 )Terakhir, saya mengelompokkan berdasarkan frame data dan mengambil nilai jarak minimum.
Inilah perpustakaan,
Berikut adalah fungsi yang digunakan,
Dan data,
Gabung silang dengan
geopandas
bingkai data,math
fungsi dangeopandas
,geopy
dangeopandas
,Jika Anda ingin menggunakan
pandas
bukangeopandas
,Dengan
math
fungsi,Dengan
geopy
,sumber
geopy.distance.distance()
3 jarak yang sama adalah (bulat)2285
,4629
dan4227
km.geopy
, sebagai situs web saya percaya lebih banyak edwilliams.org/gccalc.htm , yang setuju dengangeopy
. Situs web dari NOAA, nhc.noaa.gov/gccalc.shtml , mengatakan ini didasarkan pada yang pertama, tetapi kemudian menghasilkan hasil yang berbeda. Mungkin didasarkan pada versi lama dari yang lama.Saya pikir cukup sulit untuk menemukan solusi dengan kompleksitas waktu yang lebih baik daripada O (m · n) , di mana m dan n adalah ukuran
city1
dancity2
. Menjaga perbandingan jarak (satu-satunya operasi O (m · n)) sederhana, dan mengambil keuntungan dari operasi vektor yang disediakan oleh numpy dan panda, kecepatan seharusnya tidak menjadi masalah untuk ukuran input yang masuk akal.Idenya adalah bahwa, untuk membandingkan jarak pada bola, Anda dapat membandingkan jarak antara titik-titik dalam 3D. Kota terdekat adalah juga yang paling dekat lewat melalui bola. Selain itu, Anda biasanya mengambil akar kuadrat untuk menghitung jarak, tetapi jika Anda hanya perlu membandingkannya, Anda dapat menghindari akar kuadrat.
Perhatikan bahwa setiap solusi yang menggunakan lintang dan bujur seolah-olah mereka adalah koordinat Cartesius salah, karena bergerak ke kutub meridian (garis bujur yang sama) semakin dekat satu sama lain.
sumber
Solusi ini mungkin bukan cara tercepat untuk menyelesaikan masalah Anda, tetapi saya yakin ini akan berhasil.
Jika Anda perlu bekerja pada meter dan bukan derajat, Anda selalu dapat memproyeksi ulang layer Anda (itu juga akan menghapus kesalahan yang dimaksudkan Walter). Anda dapat melakukannya dengan
gcity3df = gcity3df.to_crs({'init': 'epsg:XXXX'})
XXXX sebagai kode epsg untuk CR yang digunakan di wilayah dunia Anda.sumber