Hier ist mein erster Geodatframe:
!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))
Stadt1
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)
und mein zweiter Geodatenrahmen: 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)
Ich möchte einen dritten Datenrahmen mit der nächstgelegenen Stadt von Stadt1 zu Stadt2 mit der Entfernung wie:
City Country Latitude Longitude geometry Nearest Distance
0 Buenos Aires Argentina -34.58 -58.66 POINT (-58.66000 -34.58000) Bogota 111 Km
Hier ist meine eigentliche Lösung mit Geodjango und Diktat (aber es ist viel zu lang):
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']
Hier sind meine Versuche:
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
Hier :
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
Grüße
Antworten:
Zunächst füge ich zwei Datenrahmen durch Cross-Join zusammen. Und dann fand ich mit
map
Python Abstand zwischen zwei Punkten . Ich benutzemap
, weil die meiste Zeit es viel schneller als istapply
,itertuples
,iterrows
usw. (Referenz: https://stackoverflow.com/a/52674448/8205554 )Zuletzt gruppiere ich nach Datenrahmen und rufe Mindestabstandswerte ab.
Hier sind Bibliotheken,
Hier werden Funktionen verwendet,
Und Daten,
Cross Join mit
geopandas
Datenrahmen,math
Funktionen undgeopandas
,geopy
undgeopandas
,Wenn Sie
pandas
anstelle von verwenden möchtengeopandas
,Mit
math
Funktionen,Mit
geopy
,quelle
geopy.distance.distance()
der gleichen 3 Abstände (gerundet)2285
,4629
und4227
km.geopy
, vertraue ich als Website mehr edwilliams.org/gccalc.htm , was zustimmtgeopy
. Die Website der NOAA, nhc.noaa.gov/gccalc.shtml , sagt, dass sie auf der ersteren basiert, dann aber unterschiedliche Ergebnisse liefert. Es basiert wahrscheinlich auf einer alten Version der ersteren.Ich denke, es ist ziemlich schwierig, eine Lösung mit einer Zeitkomplexität zu finden, die besser ist als O (m · n) , wobei m und n die Größen von
city1
und sindcity2
. Wenn Sie den Abstandsvergleich (die einzige O (m · n) -Operation) einfach halten und die vektorisierten Operationen von Numpy und Pandas nutzen, sollte die Geschwindigkeit für keine vernünftige Eingabegröße ein Problem sein.Die Idee ist, dass Sie zum Vergleichen von Entfernungen auf einer Kugel die Entfernungen zwischen den Punkten in 3D vergleichen können. Die nächstgelegene Stadt ist auch die nächstgelegene, die durch die Kugel verläuft. Außerdem verwenden Sie normalerweise Quadratwurzeln, um Entfernungen zu berechnen. Wenn Sie diese jedoch nur vergleichen müssen, können Sie die Quadratwurzeln vermeiden.
Beachten Sie, dass jede Lösung, bei der Breiten- und Längengrade wie kartesische Koordinaten verwendet werden, falsch ist, da sich die Meridiane (Linien gleicher Länge) in Richtung der Pole nähern.
quelle
Diese Lösung ist wahrscheinlich nicht der schnellste Weg, um Ihr Problem zu lösen, aber ich glaube, es wird den Trick tun.
Wenn Sie an Metern und nicht an Grad arbeiten müssen, können Sie Ihre Ebene jederzeit neu projizieren (dies löscht auch den Fehler, den Walter meint). Sie können dies tun, indem
gcity3df = gcity3df.to_crs({'init': 'epsg:XXXX'})
XXXX der Epsg-Code für Crs ist, die in Ihrer Weltregion verwendet werden.quelle