Я имел эту проблему и, поскольку этот вопрос 5 лет, мне пришлось переделывать все тесты и изменить синтаксис узкого места (нет partsort
больше, это partition
сейчас).
Я использовал те же аргументы, что и kwgoodman, за исключением числа извлеченных элементов, которое я увеличил до 50 (чтобы лучше соответствовать моей конкретной ситуации).
я получил следующие результаты:
bottleneck 1: 01.12 ms per loop
bottleneck 2: 00.95 ms per loop
pandas : 01.65 ms per loop
heapq : 08.61 ms per loop
numpy : 12.37 ms per loop
numpy 2 : 00.95 ms per loop
Так, bottleneck_2 и numpy_2 (решение Ādas) бросались привязанные. Но, используя np.percentile
(numpy_2), у вас есть те элементы topN, которые уже отсортированы, что не относится к другим решениям. С другой стороны, если вас интересуют индексы этих элементов, процентиль не является полезным.
Я также добавил панды, в которых используется узкое место внизу, если доступно (http://pandas.pydata.org/pandas-docs/stable/install.html#recommended-dependencies).Если у вас уже есть серия pandas или DataFrame, вы в хороших руках, просто используйте nlargest
, и все готово.
Код, используемый в тесте выглядит следующим образом (питон 3, пожалуйста):
import time
import numpy as np
import bottleneck as bn
import pandas as pd
import heapq
def bottleneck_1(a, n):
return -bn.partition(-a, n)[:n]
def bottleneck_2(a, n):
return bn.partition(a, a.size-n)[-n:]
def numpy(a, n):
return a[a.argsort()[-n:]]
def numpy_2(a, n):
M = a.shape[0]
perc = (np.arange(M-n,M)+1.0)/M*100
return np.percentile(a,perc)
def pandas(a, n):
return pd.Series(a).nlargest(n)
def hpq(a, n):
return heapq.nlargest(n, a)
def do_nothing(a, n):
return a[:n]
def benchmark(func, size=1000000, ntimes=100, topn=50):
t1 = time.time()
for n in range(ntimes):
a = np.random.rand(size)
func(a, topn)
t2 = time.time()
ms_per_loop = 1000000 * (t2 - t1)/size
return ms_per_loop
t1 = benchmark(bottleneck_1)
t2 = benchmark(bottleneck_2)
t3 = benchmark(pandas)
t4 = benchmark(hpq)
t5 = benchmark(numpy)
t6 = benchmark(numpy_2)
t0 = benchmark(do_nothing)
print("bottleneck 1: {:05.2f} ms per loop".format(t1 - t0))
print("bottleneck 2: {:05.2f} ms per loop".format(t2 - t0))
print("pandas : {:05.2f} ms per loop".format(t3 - t0))
print("heapq : {:05.2f} ms per loop".format(t4 - t0))
print("numpy : {:05.2f} ms per loop".format(t5 - t0))
print("numpy 2 : {:05.2f} ms per loop".format(t6 - t0))
Возможный дубликат [Как получить индексы максимальных значений N в Numpy массиве?] (HTTP: // StackOverflow .com/questions/6910641/how-to-get-index-of-n-maximum-values-in-numpy-array) – Seanny123