我试图在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
答案 0 :(得分:3)
对于那些您对部分排序索引感兴趣的案例,有NumPy's argpartition
。
您遇到了麻烦np.argsort
:w[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
会尝试按升序排序索引。所以,要反转它,我们已经否定了元素。
因此,原始代码的建议更改将是:
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
答案 1 :(得分:1)
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
上答案 2 :(得分:0)
您的输入和输出有点令人困惑。请提供一些示例数据。
但请看:http://pandas.pydata.org/pandas-docs/stable/api.html#reshaping-sorting-transposing Pandas排序是最优化的。关注系列排序,因为DataFrame的每一列都更准确地表示为系列。