首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Pandas Dataframe中运行外部函数以加快处理循环

在Pandas Dataframe中运行外部函数以加快处理循环
EN

Stack Overflow用户
提问于 2022-07-12 10:31:46
回答 2查看 55关注 0票数 0

你好,小鬼头,

我目前有两个数据帧,“位置”和"Pokestops",都包含一个坐标列表。这两个数据帧的目标是将"Pokestops“中距离”地点“70米以内的点进行聚类。

我创建了一个"Brute Force“集群脚本。

这一过程如下:

  1. 计算“地点”中每个点70米以内的"Pokestops“。
  2. 将所有附近的Pokestops添加到“Pokestops”位置,作为索引值(例如,(0,4,22)的列表/数组)
  3. 如果没有Pokestops在“位置”中的某个点附近,请从位置df中移除这一行。
代码语言:javascript
运行
复制
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)

这导致:

代码语言:javascript
运行
复制
           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
  1. 按照七千万以内的数量最多到最少的数量排序。
代码语言:javascript
运行
复制
locations.sort_values("Length", ascending=False, inplace=True)

这导致:

代码语言:javascript
运行
复制
           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
  1. 从所有其他行( Locations0:,"Pokestops“)中删除Locations0中列出的所有索引值"Pokestops”
代码语言:javascript
运行
复制
    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

这导致:

代码语言:javascript
运行
复制
           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
  1. 删除位置中的所有空行“Pokestops”
代码语言:javascript
运行
复制
locations = locations[locations['Pokestops'].map(len)>0]

这导致:

代码语言:javascript
运行
复制
           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
  1. 将Locations0,“坐标”添加到一个数组中,该数组稍后可以保存到.txt,这将形成我们的“集群”坐标的最终列表。
代码语言:javascript
运行
复制
clusters = np.append(clusters, locations.iloc[0 , 0:2])

这导致:

代码语言:javascript
运行
复制
           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
  1. 从4-7重复这个过程,直到位置df为空。

这所有的结果都是一个数组,其中包含从位置数据from到Pokestops 70m范围内的所有点的坐标,从最大到最小的集群排序。

现在是实际问题。

我在步骤1-3中使用的方法导致需要为一个中小型数据集循环几百万次。

我相信,我可以实现更快的时间,从使用"for“循环迁移,并允许Pandas使用geopy.distance.geodesic函数”直接“计算两个表之间的距离。

我只是不知道该怎么处理.

  • 如何使它在不使用for循环的情况下迭代行?
  • 如何使用位置“Pokestops”列中的“列表/数组”来维护?
  • 会更快吗?

我知道有一个名为GeoPandas的库,但这需要conda,这意味着我需要避免在“Pokestops”列位置使用我的数组/列表。(我对如何公平地使用GeoPandas也有0的知识)

我知道像这样的广泛问题通常都被回避,但我在蟒蛇方面是完全自学的,我试图达到一个脚本中最可能太复杂的程度。

我已经做到了这一点,我只是需要最后一步,使它更有效率。脚本完全正常工作,并且提供了所需的结果,由于嵌套的for循环,运行时间太长了。

任何建议/想法都会受到极大的赞赏,请记住,我对python/Pandas的知识是有限的,而且我也不知道所有的功能/术语。

编辑#1:

谢谢你@Finn,虽然这个解决方案使我的主体发生了很大的变化,但它还是如愿以偿。

使用新的矩阵,我将过滤everything> 0.07为NaN。

代码语言:javascript
运行
复制
          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()的每一个组合,我可以在网上找到。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-13 07:56:11

我不完全理解您的代码,但是从您的文本中可以做一些事情来加快速度。我认为最有益的事情是将你的距离计算矢量化,因为循环到每一个组合都要花费很长时间。因此,我从这个答案中窃取了计算结果,并采用它创建了一个矩阵:

代码语言:javascript
运行
复制
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 = 10degrees = 0.000009915在您的文本中是否这样做,所以您可能需要调整计算,您可能需要将6367公里与geopy.distance.geodesic的计算进行比较,如描述的这里,以获得相同的结果。

票数 0
EN

Stack Overflow用户

发布于 2022-07-12 10:41:00

应用函数可能会有所帮助。Apply函数将指定的函数应用于数据集的每个单元格(当然,您可以控制参数)。请查看此文档(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html)以获得进一步的理解。

我确实相信,一旦解决方案隐藏在多个层中,实现循环将是非常混乱的。从处理数据集的角度来看,如果没有循环方法和应用函数,情况就会好得多,因为在这里,我们需要提供快速的解决方案。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72950881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档