python - 如何提高for循环的执行时间?

标签 python sql pandas count nearest-neighbor

我有一个名为“zone”的 DF,其中 xy 列为整数,可以解释为点的位置。我需要计算第一个和第二个邻居的数量,我已经写了:

import numpy as np
import pandas as pd

data = np.random.randint(1000,6000,size=(600000,2))
zone = pd.DataFrame(data, columns=['x', 'y']).drop_duplicates()

a=[]
for i,row in zone.iterrows(): 
    x = row.x
    y = row.y
    num_1st_neigh = len(zone[(zone.x>=(x-1))&(zone.x<=(x+1))&(zone.y>=(y-1))&(zone.y<=(y+1))])-1
    num_2nd_neigh = (len(zone[(zone.x>=(x-2))&(zone.x<=(x+2))&(zone.y>=(y-2))&(zone.y<=(y+2))])-1)\
    -(num_1st_neigh)
    a.append([i,num_1st_neigh,num_2nd_neigh])
a = pd.DataFrame(a, columns = ['index','num_1st_neigh','num_2nd_neigh'])
zzz = zone.reset_index().merge(a,on='index')

这个效果很好,但在 3K 点上持续 15 秒,我有 1M 点,2 小时后它仍然运行。关于如何提高执行速度有什么想法吗?

我读到 iterrows 非常慢,但我不知道还能怎么做。

编辑:我也尝试使用 SQL 进行相同的操作,但执行时间>2小时并且查询返回超时:

SELECT t0.x,
    t0.y,
    count_if(greatest(abs(t0.x-t1.x), abs(t0.y-t1.y)) = 1) num_1_neighbors,
    count_if(greatest(abs(t0.x-t1.x), abs(t0.y-t1.y)) = 2) num_2_neighbors
FROM "table" t0 
    left join "table" t1 on t1.x between t0.x -2 and t0.x + 2
    and t1.y between t0.y -2 and t0.y + 2
    and (
        t1.x <> t0.x
        or t1.y <> t0.y
    )
group by 1,2

任何使用 SQL 或 pandas 的想法都非常受欢迎

最佳答案

您可以使用BallTree来自sklearn:

from sklearn.neighbors import BallTree

xy = zone[['x', 'y']]
tree = BallTree(xy, metric='euclidean')
num_1st_neigh = tree.query_radius(xy, r=1*np.sqrt(2), count_only=True) - 1
num_2nd_neigh = tree.query_radius(xy, r=2*np.sqrt(2), count_only=True) - 1 - num_1st_neigh
zone['num_1st_neigh'] = num_1st_neigh
zone['num_2nd_neigh'] = num_2nd_neigh

来自一个小例子:

# BallTree
>>> zone
     x    y  num_1st_neigh  num_2nd_neigh
0  106  115              0              0
1  118  104              0              0
2  119  114              0              0
3  108  103              0              2
4  103  101              0              0
5  110  105              0              1
6  103  104              0              0
7  102  119              0              0
8  106  105              0              1
9  111  114              0              0

# Your code
>>> zzz
   index    x    y  num_1st_neigh  num_2nd_neigh
0      0  106  115              0              0
1      1  118  104              0              0
2      2  119  114              0              0
3      3  108  103              0              2
4      4  103  101              0              0
5      5  110  105              0              1
6      6  103  104              0              0
7      7  102  119              0              0
8      8  106  105              0              1
9      9  111  114              0              0

关于python - 如何提高for循环的执行时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76558860/

相关文章:

python - 如何将数据帧行乘以基于行的 'attribute' 的数组?

python - SECRET_KEY 设置不能为空 ||在 Settings.py 中可用

sql - 在 PostgreSQL 中,如何插入只有一个标识列的表?

java - 即使使用不同的 Statement 对象,获取两个 ResultSet 值也会清空两个 ResultSet

python - 在 pypy3 : . 上安装 pandas 时出错 ..Microsoft Visual Studio 14.0\\VC\\BIN\\cl.exe' 失败,退出状态 2

Python import AS 因绝对导入而失败

python - 如何计算 Pandas 中每月分成几天的两个日期之间的天数

MySQL获取两个条件之间范围的id

python - pandas:如何计算唯一类别?

python-3.x - 将 Pandas 数据帧保存到 S3 的最快方法是什么?