Voici mon premier géodatframe:
!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))
Ville1
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)
et ma deuxième géodonnées: 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)
je voudrais un troisième dataframe avec la ville la plus proche de city1 à city2 avec la distance comme:
City Country Latitude Longitude geometry Nearest Distance
0 Buenos Aires Argentina -34.58 -58.66 POINT (-58.66000 -34.58000) Bogota 111 Km
Voici ma solution actuelle en utilisant geodjango et dict (mais c'est beaucoup trop long):
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']
Voici mes essais:
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
ici :
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
Cordialement
Réponses:
Tout d'abord, je fusionne deux trames de données par jointure croisée. Et puis, j'ai trouvé la distance entre deux points en utilisant
map
python. J'utilisemap
, parce que la plupart du temps , il est beaucoup plus rapide queapply
,itertuples
,iterrows
etc. (Référence: https://stackoverflow.com/a/52674448/8205554 )Enfin, je regroupe par bloc de données et récupère les valeurs minimales de distance.
Voici les bibliothèques,
Voici les fonctions utilisées,
Et les données,
Jointure croisée avec
geopandas
des trames de données,math
fonctions etgeopandas
,geopy
etgeopandas
,Si vous souhaitez utiliser
pandas
place degeopandas
,Avec
math
fonctions,Avec
geopy
,la source
geopy.distance.distance()
les mêmes 3 distances sont (arrondis)2285
,4629
et4227
km.geopy
, en tant que site Web, je fais plus confiance à edwilliams.org/gccalc.htm , ce qui est d'accordgeopy
. Le site Web de la NOAA, nhc.noaa.gov/gccalc.shtml , dit qu'il est basé sur le premier, mais donne ensuite des résultats différents. Il est probablement basé sur une ancienne version de l'ancien.Je pense qu'il est assez difficile de trouver une solution avec une complexité temporelle meilleure que O (m · n) , où m et n sont les tailles de
city1
etcity2
. Garder la comparaison de distance (la seule opération O (m · n)) simple et tirer parti des opérations vectorisées fournies par numpy et pandas, la vitesse ne devrait pas être un problème pour toute taille d'entrée raisonnable.L'idée est que, pour comparer des distances sur une sphère, vous pouvez comparer les distances entre les points en 3D. La ville la plus proche est également la plus proche qui traverse la sphère. De plus, vous prenez normalement des racines carrées pour calculer les distances, mais si vous avez seulement besoin de les comparer, vous pouvez éviter les racines carrées.
Notez que toute solution qui utilise la latitude et la longitude comme s'il s'agissait de coordonnées cartésiennes est erronée, car en se rapprochant des pôles, les méridiens (lignes de longitude égale) se rapprochent les uns des autres.
la source
Cette solution n'est probablement pas le moyen le plus rapide de résoudre votre problème, mais je pense qu'elle fera l'affaire.
Si vous devez travailler sur des mètres et non sur des degrés, vous pouvez toujours reprojeter votre couche (cela effacera également l'erreur que Walter veut dire). Vous pouvez le faire par
gcity3df = gcity3df.to_crs({'init': 'epsg:XXXX'})
où XXXX est le code epsg pour les crs utilisés dans votre région du monde.la source