你好,小鬼头,
我目前有两个数据帧,“位置”和"Pokestops",都包含一个坐标列表。这两个数据帧的目标是将"Pokestops“中距离”地点“70米以内的点进行聚类。
我创建了一个"Brute Force“集群脚本。
这一过程如下:
for i in range(len(locations)-1, -1, -1):
array = []
for f in range(0, len(pokestops)):
if geopy.distance.geodesic(locations.iloc[i, 2], pokestops.iloc[f, 2]).m <= 70:
array.append(f)
if len(array) <= 0:
locations.drop([i], inplace=True)
else:
locations.iat[i, 3] = array
locations["Length"] = locations["Pokestops"].map(len)
这导致:
Lat Long Coordinates Pokestops Length
2 -33.916432 18.426188 -33.916432,18.4261883 [1] 1
3 -33.916432 18.426287 -33.916432,18.42628745 [1] 1
4 -33.916432 18.426387 -33.916432,18.4263866 [1] 1
5 -33.916432 18.426486 -33.916432,18.42648575 [0, 1] 2
6 -33.916432 18.426585 -33.916432,18.4265849 [0, 1] 2
7 -33.916432 18.426684 -33.916432,18.426684050000002 [0, 1] 2
locations.sort_values("Length", ascending=False, inplace=True)
这导致:
Lat Long Coordinates Pokestops Length
136 -33.915441 18.426585 -33.91544050000003,18.4265849 [1, 2, 3, 4] 4
149 -33.915341 18.426585 -33.915341350000034,18.4265849 [1, 2, 3, 4] 4
110 -33.915639 18.426585 -33.915638800000025,18.4265849 [1, 2, 3, 4] 4
111 -33.915639 18.426684 -33.915638800000025,18.426684050000002 [1, 2, 3, 4] 4
stops = list(locations['Pokestops'])
seen = list(locations.iloc[0, 3])
stops_filtered = [seen]
for xx in stops[1:]:
xx = [x for x in xx if x not in seen]
stops_filtered.append(xx)
locations['Pokestops'] = stops_filtered
这导致:
Lat Long Coordinates Pokestops Length
136 -33.915441 18.426585 -33.91544050000003,18.4265849 [1, 2, 3, 4] 4
149 -33.915341 18.426585 -33.915341350000034,18.4265849 [] 4
110 -33.915639 18.426585 -33.915638800000025,18.4265849 [] 4
111 -33.915639 18.426684 -33.915638800000025,18.426684050000002 [] 4
locations = locations[locations['Pokestops'].map(len)>0]
这导致:
Lat Long Coordinates Pokestops Length
136 -33.915441 18.426585 -33.91544050000003,18.4265849 [1, 2, 3, 4] 4
176 -33.915143 18.426684 -33.91514305000004,18.426684050000002 [5] 3
180 -33.915143 18.427081 -33.91514305000004,18.427080650000004 [5] 3
179 -33.915143 18.426982 -33.91514305000004,18.426981500000004 [5] 3
clusters = np.append(clusters, locations.iloc[0 , 0:2])
这导致:
Lat Long Coordinates Pokestops Length
176 -33.915143 18.426684 -33.91514305000004,18.426684050000002 [5] 3
180 -33.915143 18.427081 -33.91514305000004,18.427080650000004 [5] 3
179 -33.915143 18.426982 -33.91514305000004,18.426981500000004 [5] 3
64 -33.916035 18.427180 -33.91603540000001,18.427179800000005 [0] 3
这所有的结果都是一个数组,其中包含从位置数据from到Pokestops 70m范围内的所有点的坐标,从最大到最小的集群排序。
现在是实际问题。
我在步骤1-3中使用的方法导致需要为一个中小型数据集循环几百万次。
我相信,我可以实现更快的时间,从使用"for“循环迁移,并允许Pandas使用geopy.distance.geodesic函数”直接“计算两个表之间的距离。
我只是不知道该怎么处理.
我知道有一个名为GeoPandas的库,但这需要conda,这意味着我需要避免在“Pokestops”列位置使用我的数组/列表。(我对如何公平地使用GeoPandas也有0的知识)
我知道像这样的广泛问题通常都被回避,但我在蟒蛇方面是完全自学的,我试图达到一个脚本中最可能太复杂的程度。
我已经做到了这一点,我只是需要最后一步,使它更有效率。脚本完全正常工作,并且提供了所需的结果,由于嵌套的for循环,运行时间太长了。
任何建议/想法都会受到极大的赞赏,请记住,我对python/Pandas的知识是有限的,而且我也不知道所有的功能/术语。
编辑#1:
谢谢你@Finn,虽然这个解决方案使我的主体发生了很大的变化,但它还是如愿以偿。
使用新的矩阵,我将过滤everything> 0.07为NaN。
Lat Long Count 0 1 2 3 4
82 -33.904620 18.402612 5 NaN NaN NaN 0.052401 NaN
75 -33.904620 18.400183 5 NaN NaN NaN NaN 0.053687
120 -33.903579 18.401224 5 NaN NaN NaN NaN NaN
68 -33.904967 18.402612 5 NaN 0.044402 NaN 0.015147 NaN
147 -33.902885 18.400877 5 NaN NaN NaN NaN NaN
89 -33.904273 18.400183 5 NaN NaN NaN NaN NaN
182 -33.901844 18.398448 4 NaN NaN NaN NaN NaN
54 -33.905314 18.402612 4 NaN 0.020793 NaN 0.026215 NaN
183 -33.901844 18.398795 4 NaN NaN NaN NaN NaN
184 -33.901844 18.399142 4 NaN NaN NaN NaN NaN
我现在面临的问题是我最初的帖子中的第五步。
您能建议我如何删除第一行中不包含NaN的所有列吗?
我唯一能找到的信息是删除列,如果任何行中的值都不是NaN。我已经尝试了.dropna()的每一个组合,我可以在网上找到。
发布于 2022-07-13 07:56:11
我不完全理解您的代码,但是从您的文本中可以做一些事情来加快速度。我认为最有益的事情是将你的距离计算矢量化,因为循环到每一个组合都要花费很长时间。因此,我从这个答案中窃取了计算结果,并采用它创建了一个矩阵:
import numpy as np
import pandas as pd
pokestops = pd.read_csv('Pokestops.txt', header=None)
pokestops.columns = ["Lat", "Long"]
locations = pd.read_csv('Locations.txt')
locations.columns = ["Lat", "Long"]
def haversine_np_matrix(lon1, lat1, lon2, lat2):
lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
lon1 = np.expand_dims(lon1, axis=0)
lat1 = np.expand_dims(lat1, axis=0)
lon2 = np.expand_dims(lon2, axis=1)
lat2 = np.expand_dims(lat2, axis=1)
dlon = lon2 - lon1
dlat = lat2 - lat1
a = np.sin(dlat/2.0)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2.0)**2
c = 2 * np.arcsin(np.sqrt(a))
km = 6367 * c
return km
distances = haversine_np_matrix(pokestops["Long"],pokestops["Lat"], locations["Long"],locations['Lat'])
这给出了从每个位置到每个Pokestop的距离。现在你可以用像distances < 0.07
这样的东西来找到所有接近70米的东西。为此,我剥夺了Location.txt的一切,但Long和Lat除外。我不确定meters = 10
和degrees = 0.000009915
在您的文本中是否这样做,所以您可能需要调整计算,您可能需要将6367公里与geopy.distance.geodesic
的计算进行比较,如描述的这里,以获得相同的结果。
发布于 2022-07-12 10:41:00
应用函数可能会有所帮助。Apply函数将指定的函数应用于数据集的每个单元格(当然,您可以控制参数)。请查看此文档(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html)以获得进一步的理解。
我确实相信,一旦解决方案隐藏在多个层中,实现循环将是非常混乱的。从处理数据集的角度来看,如果没有循环方法和应用函数,情况就会好得多,因为在这里,我们需要提供快速的解决方案。
https://stackoverflow.com/questions/72950881
复制相似问题