首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提高Pandas中行最近邻的性能

提高Pandas中行最近邻的性能
EN

Stack Overflow用户
提问于 2015-05-27 18:14:03
回答 1查看 4.1K关注 0票数 2

我得到8000x3数据集,类似于这个数据集:

代码语言:javascript
复制
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(8000,3), columns=list('XYZ'))

因此,作为视觉参考,df.head(5)如下所示:

代码语言:javascript
复制
          X         Y         Z
0  0.462433  0.559442  0.016778
1  0.663771  0.092044  0.636519
2  0.111489  0.676621  0.839845
3  0.244361  0.599264  0.505175
4  0.115844  0.888622  0.766014

我正在尝试实现一个方法,当从dataset获得索引时,它将从dataset返回类似的项(以某种合理的方式)。现在我有:

代码语言:javascript
复制
def find_similiar_items(item_id):
    tmp_df = df.sub(df.loc[item_id], axis='columns')
    tmp_series = tmp_df.apply(np.square).apply(np.sum, axis=1)
    tmp_series.sort()
    return tmp_series

此方法接受您的行,然后从dataframe中的彼此行中减去它,然后计算每一行的范数。因此,这个方法只是使用欧几里德距离将一系列最近的点返回给你的给定点。

因此,您可以得到最近的5分,例如:

代码语言:javascript
复制
df.loc[find_similiar_items(5).index].head(5)

产生的结果:

代码语言:javascript
复制
             X         Y         Z
5     0.364020  0.380303  0.623393
4618  0.369122  0.399772  0.643603
4634  0.352484  0.402435  0.619763
5396  0.386675  0.370417  0.600555
3229  0.355186  0.410202  0.616844

这个方法的问题是,每次调用它大约需要半秒钟。对于我的目的来说,这是不可接受的,所以我需要弄清楚如何在某种程度上提高这个方法的性能。所以我有几个问题:

问题1,,是否有一种更有效的方法来简单地计算上面的欧几里德距离?

问题2,还有其他一些技术,可以得到这样合理的结果(例如,欧几里德距离并不重要)。在这个问题中,计算时间比内存更重要,而预处理时间并不重要;因此,例如,我愿意构造一个大小与笛卡儿积(n^2)相同的原始数据(但任何比这更不合理的数据)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-28 12:47:17

你最大的(也是最简单的)表现可能是仅仅在矮胖的熊猫身上做这个。从代码快速转换到numpy,我看到了超过200倍的改进:

代码语言:javascript
复制
arr = df.values
def fsi_numpy(item_id):
    tmp_arr = arr - arr[item_id]
    tmp_ser = np.sum( np.square( tmp_arr ), axis=1 )
    return tmp_ser

df['dist'] = fsi_numpy(5)
df = df.sort_values('dist').head(5)

             X         Y         Z      dist
5     0.272985  0.131939  0.449750  0.000000
5130  0.272429  0.138705  0.425510  0.000634
4609  0.264882  0.103006  0.476723  0.001630
1794  0.245371  0.175648  0.451705  0.002677
6937  0.221363  0.137457  0.463451  0.002883

检查它是否给出与您的函数相同的结果(因为我们有不同的随机抽签):

代码语言:javascript
复制
df.loc[ pd.DataFrame( find_similiar_items(5)).index].head(5)

             X         Y         Z
5     0.272985  0.131939  0.449750
5130  0.272429  0.138705  0.425510
4609  0.264882  0.103006  0.476723
1794  0.245371  0.175648  0.451705
6937  0.221363  0.137457  0.463451

计时:

代码语言:javascript
复制
%timeit df.loc[ pd.DataFrame( find_similiar_items(5)).index].head(5)
1 loops, best of 3: 638 ms per loop

In [105]: %%timeit
     ...: df['dist'] = fsi_numpy(5)
     ...: df = df.sort_values('dist').head(5)
     ...: 
100 loops, best of 3: 2.69 ms per loop
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30490147

复制
相关文章

相似问题

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