【问题标题】:Fastest way to sort a large number of arrays in python在python中对大量数组进行排序的最快方法
【发布时间】:2016-08-30 07:48:46
【问题描述】:

我正在尝试在 python 中对大量数组进行排序。我需要一次对超过 1100 万个数组进行排序。

另外,如果我可以直接获取对数组进行排序的索引,那就太好了。

这就是为什么,到目前为止,我正在使用 numpy.argsort() 但这在我的机器上太慢了(需要一个多小时才能运行)

R 中的相同操作在同一台机器上大约需要 15 分钟。

谁能告诉我在 Python 中执行此操作的更快方法?

谢谢

编辑

添加示例

如果我有以下数据框:

agg:

x      y        w        z  

1      2        2        5                 
1      2        6        7         
3      4        3        3        
5      4        7        8    
3      4        2        5    
5      9        9        9    

我正在运行以下函数和命令:

def fucntion(group):
    z = group['z'].values   
    w = group['w'].values 
    func = w[np.argsort(z)[::-1]][:7]  #i need top 7 in case there are many  
    return np.array_str(func)[1:-1]

output = agg.groupby(['x,'y']).apply(function).reset_index()

所以我的输出数据框将如下所示:

output:

x   y   w   

1   2   6,2    
3   4   2,3    
5   4   7    
5   9   9

【问题讨论】:

  • 您输入的具体内容是什么?它是数组列表吗?你能添加一个示例输入案例吗?
  • 它是 pandas 数据框列的一部分。
  • 除了您尝试过的内容之外,您能否提供一些示例数据和所需的输出?
  • 您知道axisargsort 的参数吗?
  • 不,我不是。 @用户2357112。我读过它,我真的不认为它会为我完成这项工作。

标签: python performance sorting numpy pandas


【解决方案1】:

对于像您对部分排序索引感兴趣的情况,有NumPy's argpartition

你有麻烦的np.argsortw[np.argsort(z)[::-1]][:7],本质上是w[idx],其中idx = np.argsort(z)[::-1][:7]

所以,idx 可以用 np.argpartition 计算,就像这样 -

idx = np.argpartition(-z,np.arange(7))[:7]

-z 是必需的,因为默认情况下np.argpartition 尝试按升序获取排序索引。所以,为了 reverse 它,我们已经否定了元素。

因此,对原始代码的建议更改为:

func = w[np.argpartition(-z,np.arange(7))[:7]]

运行时测试-

In [162]: z = np.random.randint(0,10000000,(1100000)) # Random int array

In [163]: idx1 = np.argsort(z)[::-1][:7]
     ...: idx2 = np.argpartition(-z,np.arange(7))[:7]
     ...: 

In [164]: np.allclose(idx1,idx2) # Verify results
Out[164]: True

In [165]: %timeit np.argsort(z)[::-1][:7]
1 loops, best of 3: 264 ms per loop

In [166]: %timeit np.argpartition(-z,np.arange(7))[:7]
10 loops, best of 3: 36.5 ms per loop

【讨论】:

  • 这是一个很好的解决方案,但是如果在我的数据框中的某个地方,要排序的数字小于 7,那么我认为它不会起作用。 (有可能,输出最多需要7个)
  • @GunjanDewan 那么,只需将此处的7 替换为该数字即可?您可以将其保留为变量并让变量处理它吗?类似于n = 5; func = w[np.argpartition(-z,np.arange(n))[:n]],其中n 是那个变量。
  • @GunjanDewan 或者你是说z 本身可能小于7 元素?
  • 是的。 z 本身可以小于 7。但我在 len(z) 上添加了一个变量。我目前在我的数据集上运行它。我希望它运行得更快。
  • @GunjanDewan 是的,这就是我要建议的,使用n = min(len(z),7),然后使用func = w[np.argpartition(-z,np.arange(n))[:n]]。也希望看到您的运行时结果!随时通知我。
【解决方案2】:

python 比 R 慢得多的原因是 python 不会对变量进行类型转换(即 int、string、float),因此每次比较确定哪个值更大的部分都用于确定变量类型。

你不能单独使用 python 解决这个问题,但是你可以使用 cython 包含类型定义(ctypes 和 psyco 也可以执行相同的功能,但我更喜欢 cython)。 http://docs.cython.org/src/quickstart/cythonize.html 上有一个简单的例子来说明它是如何工作的

Cython 编译您的 python 文件的 .c 版本,可以导入该文件而不是 .py 以减少运行时间。使用 cython 编译的所有可能方式都显示在 http://docs.cython.org/src/reference/compilation.html

【讨论】:

  • 您似乎忽略或错过了提问者使用 NumPy 的事实。 NumPy 和 R 需要彼此进行类似数量的类型检查;两者都只需要在排序时检查一次数组的元素类型,而不是每次比较一次。
【解决方案3】:

您的输入和输出有点混乱。请提供一些示例数据。

但请查看:http://pandas.pydata.org/pandas-docs/stable/api.html#reshaping-sorting-transposing Pandas 排序已尽可能优化。专注于系列排序,因为 DataFrame 的每一列都更准确地表示为系列。

【讨论】:

  • 我已经对其进行了进一步的编辑。请告诉我现在是否清楚。
  • Gunjan 你想在这里做什么?你能口头解释一下你想让它做什么。这个例子是没有意义的,如果没有解释你想要什么,那么问题的解决方案就仅限于你的代码。
猜你喜欢
  • 1970-01-01
  • 2015-06-28
  • 2011-10-14
  • 2011-09-10
  • 1970-01-01
  • 2017-09-14
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多