寻找最近的邻居

Find nearest neighbors

我有一个大型数据框,格式为:

    user_id  time_interval  A      B       C       D       E       F       G       H    ... Z
0   12166    2.0            3.0    1.0     1.0     1.0     3.0     1.0     1.0     1.0  ... 0.0
1   12167    0.0            0.0    1.0     0.0     0.0     1.0     0.0     0.0     1.0  ... 0.0
2   12168    0.0            0.0    1.0     0.0     0.0     1.0     0.0     0.0     1.0  ... 0.0
3   12169    0.0            0.0    1.0     0.0     0.0     1.0     0.0     0.0     1.0  ... 0.0
4   12170    0.0            0.0    1.0     0.0     0.0     1.0     0.0     0.0     1.0  ... 0.0
... ...      ...            ...    ...     ...     ...     ...     ...     ...     ...  ... ...

我想为每个 user_id 找到基于列 A-Z 作为坐标的 'radius' 距离 r 内的最近邻居。例如,输出应该类似于 r=0.1:

user_id    neighbors
12166      [12251,12345, ...]
12167      [12168, 12169,12170, ...]
...        ...

我尝试在整个 user_id 列表中进行循环,但这需要很长时间。 我做了这样的事情:

import scipy
neighbors = []
for i in range(len(dataframe)):
    user_neighbors = [dataframe["user_id"][j] for j in range(i+1,len(dataframe)) if scipy.spatial.distance.euclidean(dataframe.values[i][2:],dataframe.values[j][2:])<0.1]
    neighbors.append([dataframe["user_id"][i],user_neighbors])

我已经等了几个小时了。 有没有 pythonic 的方法来改进这个?

这是我使用 apply 方法完成的方法。 虚拟数据由 A-D 列组成,并为邻居添加了列:

print(df)
user_id  time_interval  A  B  C  D  neighbors
0    12166              2  3  2  2  3        NaN
1    12167              0  1  4  3  3        NaN
2    12168              0  4  3  3  1        NaN
3    12169              0  2  2  3  2        NaN
4    12170              0  3  3  1  1        NaN

自定义函数:

def func(row):
    r = 2.5 # the threshold
    out = df[(((df.iloc[:, 2:-1] - row[2:-1])**2).sum(axis=1)**0.5).le(r)]['user_id'].to_list()
    out.remove(row['user_id'])
    df.loc[row.name, ['neighbors']] = str(out)
df.apply(func, axis=1)

输出:

   print(df):
   user_id  time_interval  A  B  C  D              neighbors
   0    12166              2  3  2  2  3         [12169, 12170]
   1    12167              0  1  4  3  3                [12169]
   2    12168              0  4  3  3  1         [12169, 12170]
   3    12169              0  2  2  3  2  [12166, 12167, 12168]
   4    12170              0  3  3  1  1         [12166, 12168]

让我知道它是否优于 for 循环方法。