【问题标题】:Find nearest neighbors查找最近的邻居
【发布时间】:2020-11-05 21:00:39
【问题描述】:

我有一个大型数据框:

    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
... ...      ...            ...    ...     ...     ...     ...     ...     ...     ...  ... ...

我想根据 A-Z 列作为坐标,为每个 user_id 找到“半径”距离 r 内的最近邻居。例如,对于 r=0.1,输出应如下所示:

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

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

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的方法来改进这个?

【问题讨论】:

  • 也请与我们分享您已经尝试过的方法以及为什么它不起作用。
  • 我编辑了。我尝试在整个 user_id 列表中循环,但需要很长时间
  • @stellasia 我不知道为什么我的尝试没有出现在第一版中。我刚刚重新编辑了这个问题,现在它正在显示

标签: python pandas nearest-neighbor


【解决方案1】:

这是我使用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 循环方法。

【讨论】:

  • 第一个答案我得到IndexingError: Too many indexers 最近的编辑器有一个问题,因为 df 现在没有定义为参数,所以它也不起作用
  • 首先 if 给出的 df 没有定义,因为它没有在函数内部定义。因此,我将所有内容都更改为 df,我的意思是 row=df,然后它显示 Too many indexers,它位于 .iloc 行中
  • df 应该与您的数据框名称相同,并且不需要在您的函数中定义。让行保持原样,它包含应用当前正在处理的行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 2019-11-28
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多