我正在努力计算多个纬度和经度坐标集之间的距离。简而言之,我发现了许多使用数学或geopy的教程。当我只想找到一组coordindates(或两个独特位置)之间的距离时,这些教程非常有用。但是,我的目标是扫描具有400k组原点和目标坐标的数据集。下面列出了我使用的代码的一个示例,但是当我的数组是>时,我似乎遇到了错误。 1条记录。任何有用的提示将不胜感激。谢谢。
# starting dataframe is df
lat1 = df.lat1.as_matrix()
long1 = df.long1.as_matrix()
lat2 = df.lat2.as_matrix()
long2 = df.df_long2.as_matrix()
from geopy.distance import vincenty
point1 = (lat1, long1)
point2 = (lat2, long2)
print(vincenty(point1, point2).miles)
答案 0 :(得分:4)
修改:here's a simple notebook example
一种通用方法,假设您有一个包含点的DataFrame列,并且您想要计算所有这些列之间的距离(例如,如果您有单独的列,则首先将它们组合成(lon, lat)
个元组)。将新列命名为coords
。
import pandas as pd
import numpy as np
from geopy.distance import vincenty
# assumes your DataFrame is named df, and its lon and lat columns are named lon and lat. Adjust as needed.
df['coords'] = zip(df.lat, df.lon)
# first, let's create a square DataFrame (think of it as a matrix if you like)
square = pd.DataFrame(
np.zeros(len(df) ** 2).reshape(len(df), len(df)),
index=df.index, columns=df.index)
此函数使用输入列名称从df
DataFrame中查找“end”坐标,然后使用{{1}将geopy vincenty()
函数应用于输入列中的每一行}列作为第一个参数。这是有效的,因为该功能从右到左按列逐列。
square.coords
现在我们已准备好计算所有距离
我们正在转置DataFrame(def get_distance(col):
end = df.ix[col.name]['coords']
return df['coords'].apply(vincenty, args=(end,), ellipsoid='WGS-84')
),因为我们将用于检索距离的.T
方法是指索引标签,行标签。但是,我们的内部应用函数(见上文)使用检索值
loc[]
您的distances = square.apply(get_distance, axis=1).T
值(IIRC)以公里为单位返回,因此您可能需要使用geopy
,.meters
等将这些值转换为您要使用的任何单位。
以下内容应该有效:
.miles
您现在可以使用以下方法索引距离矩阵: def units(input_instance):
return input_instance.meters
distances_meters = distances.applymap(units)
。
你应该能够很容易地适应上述内容。您可能需要调整loc[row_index, column_index]
函数中的apply
调用,以确保将正确的值传递给get_distance
。大熊猫apply
文档可能很有用,特别是在使用great_circle
传递位置参数方面(你需要最近的pandas版本才能使用)。
此代码尚未进行分析,可能有更快的方法,但400k距离计算应该相当快。
我不记得geopy是否期望坐标为args
或(lon, lat)
。我打赌这是后者(叹气)。
答案 1 :(得分:0)
我最近不得不做类似的工作,我结束了写一个我认为很容易理解和调整您的需求的解决方案,但可能不是最好/最快的:
这与urschrei发布的内容非常相似:假设您希望从Pandas DataFrame获得每两个连续坐标之间的距离,我们可以编写一个函数来处理开始和< 路径的strong>完成,计算距离,然后构造一个新的DataFrame作为返回值:
import pandas as pd
from geopy import Point, distance
def get_distances(coords: pd.DataFrame,
col_lat='lat',
col_lon='lon',
point_obj=Point) -> pd.DataFrame:
traces = len(coords) -1
distances = [None] * (traces)
for i in range(traces):
start = point_obj((coords.iloc[i][col_lat], coords.iloc[i][col_lon]))
finish = point_obj((coords.iloc[i+1][col_lat], coords.iloc[i+1][col_lon]))
distances[i] = {
'start': start,
'finish': finish,
'path distance': distance.geodesic(start, finish),
}
return pd.DataFrame(distances)
coords = pd.DataFrame({
'lat': [-26.244333, -26.238000, -26.233880, -26.260000, -26.263730],
'lon': [-48.640946, -48.644670, -48.648480, -48.669770, -48.660700],
})
print('-> coords DataFrame:\n', coords)
print('-'*79, end='\n\n')
distances = get_distances(coords)
distances['total distance'] = distances['path distance'].cumsum()
print('-> distances DataFrame:\n', distances)
print('-'*79, end='\n\n')
# Or if you want to use tuple for start/finish coordinates:
print('-> distances DataFrame using tuples:\n', get_distances(coords, point_obj=tuple))
print('-'*79, end='\n\n')
-> coords DataFrame:
lat lon
0 -26.244333 -48.640946
1 -26.238000 -48.644670
2 -26.233880 -48.648480
3 -26.260000 -48.669770
4 -26.263730 -48.660700
-------------------------------------------------------------------------------
-> distances DataFrame:
start finish \
0 26 14m 39.5988s S, 48 38m 27.4056s W 26 14m 16.8s S, 48 38m 40.812s W
1 26 14m 16.8s S, 48 38m 40.812s W 26 14m 1.968s S, 48 38m 54.528s W
2 26 14m 1.968s S, 48 38m 54.528s W 26 15m 36s S, 48 40m 11.172s W
3 26 15m 36s S, 48 40m 11.172s W 26 15m 49.428s S, 48 39m 38.52s W
path distance total distance
0 0.7941932910049856 km 0.7941932910049856 km
1 0.5943709651000332 km 1.3885642561050187 km
2 3.5914909016938505 km 4.980055157798869 km
3 0.9958396130609087 km 5.975894770859778 km
-------------------------------------------------------------------------------
-> distances DataFrame using tuples:
start finish path distance
0 (-26.244333, -48.640946) (-26.238, -48.64467) 0.7941932910049856 km
1 (-26.238, -48.64467) (-26.23388, -48.64848) 0.5943709651000332 km
2 (-26.23388, -48.64848) (-26.26, -48.66977) 3.5914909016938505 km
3 (-26.26, -48.66977) (-26.26373, -48.6607) 0.9958396130609087 km
-------------------------------------------------------------------------------
答案 2 :(得分:0)
截至 5 月 19 日
对于处理多个地理位置数据的任何人,您可以修改上述代码,但稍作修改以读取数据驱动器中的 CSV 文件。代码将在标记的文件夹中写入输出距离。
import pandas as pd
from geopy import Point, distance
def get_distances(coords: pd.DataFrame,
col_lat='lat',
col_lon='lon',
point_obj=Point) -> pd.DataFrame:
traces = len(coords) -1
distances = [None] * (traces)
for i in range(traces):
start = point_obj((coords.iloc[i][col_lat], coords.iloc[i][col_lon]))
finish = point_obj((coords.iloc[i+1][col_lat], coords.iloc[i+1][col_lon]))
distances[i] = {
'start': start,
'finish': finish,
'path distance': distance.geodesic(start, finish),
}
output = pd.DataFrame(distances)
output.to_csv('geopy_output.csv')
return output
我使用了相同的代码并为超过 50,000 个坐标生成了距离数据。