Geopandas:像循环图一样对点样本进行排序
Geopandas : sort a sample of points like a cycle graph
我正在尝试使用 geopandas 来处理一些点数据。我的最终 GeoDataFrame 在那里表示:
为了使用an other Python module which calculates the shortest road between two points with OSM data, I must sort my points like a tour。
如果不是,下一个 Python 模块计算最短路线,但不一定在最近的点之间。主要问题是游览的限制。
如果我的点只是在一条线上,那么对每个点的纬度和经度进行基本排序功能就足够了,例如:
df1 = pd.read_csv("file.csv", sep = ",")
df1 = df1.sort_values(['Latitude','Longitude'], ascending = [1,1])
# (I'm starting with pandas df before GeoDataFrame conversion)
如果我们从上一张图片的"upper"点开始排序,DataFrame的第二个点将是离它最近的,依此类推...直到第五个点,在右边图片(所以不再是最近的)...
所以我的问题是:有人知道如何实现这种特殊排序,还是我必须手动更改索引?
如果我对你的问题的理解正确,你想重新排列点的顺序以创建最短的可能路径。
我也 运行 遇到了同样的问题。
这是接受常规数据框的函数(=每个坐标都有单独的字段。我相信您可以修改任一函数以接受地理数据框或数据框,以便将几何字段拆分为 x 和 y 字段。
def autoroute_points_df(points_df, x_col="e",y_col="n"):
'''
Function, that converts a list of random points into ordered points, searching for the shortest possible distance between the points.
Author: Marjan Moderc, 2016
'''
points_list = points_df[[x_col,y_col]].values.tolist()
# arrange points in by ascending Y or X
points_we = sorted(points_list, key=lambda x: x[0])
points_sn = sorted(points_list, key=lambda x: x[1])
# Calculate the general direction of points (North-South or West-East) - In order to decide where to start the path!
westmost_point = points_we[0]
eastmost_point = points_we[-1]
deltay = eastmost_point[1] - westmost_point[1]
deltax = eastmost_point[0] - westmost_point[0]
alfa = math.degrees(math.atan2(deltay, deltax))
azimut = (90 - alfa) % 360
# If main directon is towards east (45°-135°), take westmost point as starting line.
if (azimut > 45 and azimut < 135):
points_list = points_we
elif azimut > 180:
raise Exception("Error while computing the azimuth! It cant be bigger then 180 since first point is west and second is east.")
else:
points_list = points_sn
# Create output (ordered df) and populate it with the first one already.
ordered_points_df = pd.DataFrame(columns=points_df.columns)
ordered_points_df = ordered_points_df.append(points_df.ix[(points_df[x_col]==points_list[0][0]) & (points_df[y_col]==points_list[0][1])])
for iteration in range(0, len(points_list) - 1):
already_ordered = ordered_points_df[[x_col,y_col]].values.tolist()
current_point = already_ordered[-1] # current point
possible_candidates = [i for i in points_list if i not in already_ordered] # list of candidates
distance = 10000000000000000000000
best_candidate = None
for candidate in possible_candidates:
current_distance = Point(current_point).distance(Point(candidate))
if current_distance < distance:
best_candidate = candidate
distance = current_distance
ordered_points_df = ordered_points_df.append(points_df.ix[(points_df[x_col]==best_candidate[0]) & (points_df[y_col]==best_candidate[1])])
return ordered_points_df
希望它能解决您的问题!
我正在尝试使用 geopandas 来处理一些点数据。我的最终 GeoDataFrame 在那里表示:
为了使用an other Python module which calculates the shortest road between two points with OSM data, I must sort my points like a tour。
如果不是,下一个 Python 模块计算最短路线,但不一定在最近的点之间。主要问题是游览的限制。
如果我的点只是在一条线上,那么对每个点的纬度和经度进行基本排序功能就足够了,例如:
df1 = pd.read_csv("file.csv", sep = ",")
df1 = df1.sort_values(['Latitude','Longitude'], ascending = [1,1])
# (I'm starting with pandas df before GeoDataFrame conversion)
如果我们从上一张图片的"upper"点开始排序,DataFrame的第二个点将是离它最近的,依此类推...直到第五个点,在右边图片(所以不再是最近的)...
所以我的问题是:有人知道如何实现这种特殊排序,还是我必须手动更改索引?
如果我对你的问题的理解正确,你想重新排列点的顺序以创建最短的可能路径。
我也 运行 遇到了同样的问题。 这是接受常规数据框的函数(=每个坐标都有单独的字段。我相信您可以修改任一函数以接受地理数据框或数据框,以便将几何字段拆分为 x 和 y 字段。
def autoroute_points_df(points_df, x_col="e",y_col="n"):
'''
Function, that converts a list of random points into ordered points, searching for the shortest possible distance between the points.
Author: Marjan Moderc, 2016
'''
points_list = points_df[[x_col,y_col]].values.tolist()
# arrange points in by ascending Y or X
points_we = sorted(points_list, key=lambda x: x[0])
points_sn = sorted(points_list, key=lambda x: x[1])
# Calculate the general direction of points (North-South or West-East) - In order to decide where to start the path!
westmost_point = points_we[0]
eastmost_point = points_we[-1]
deltay = eastmost_point[1] - westmost_point[1]
deltax = eastmost_point[0] - westmost_point[0]
alfa = math.degrees(math.atan2(deltay, deltax))
azimut = (90 - alfa) % 360
# If main directon is towards east (45°-135°), take westmost point as starting line.
if (azimut > 45 and azimut < 135):
points_list = points_we
elif azimut > 180:
raise Exception("Error while computing the azimuth! It cant be bigger then 180 since first point is west and second is east.")
else:
points_list = points_sn
# Create output (ordered df) and populate it with the first one already.
ordered_points_df = pd.DataFrame(columns=points_df.columns)
ordered_points_df = ordered_points_df.append(points_df.ix[(points_df[x_col]==points_list[0][0]) & (points_df[y_col]==points_list[0][1])])
for iteration in range(0, len(points_list) - 1):
already_ordered = ordered_points_df[[x_col,y_col]].values.tolist()
current_point = already_ordered[-1] # current point
possible_candidates = [i for i in points_list if i not in already_ordered] # list of candidates
distance = 10000000000000000000000
best_candidate = None
for candidate in possible_candidates:
current_distance = Point(current_point).distance(Point(candidate))
if current_distance < distance:
best_candidate = candidate
distance = current_distance
ordered_points_df = ordered_points_df.append(points_df.ix[(points_df[x_col]==best_candidate[0]) & (points_df[y_col]==best_candidate[1])])
return ordered_points_df
希望它能解决您的问题!