我希望加快以下代码的速度:
NNlist=[np.unique(i) for i in NNlist]
其中 NNlist 是具有重复条目的 np.arrays 列表。
谢谢 :)
我希望加快以下代码的速度:
NNlist=[np.unique(i) for i in NNlist]
其中 NNlist 是具有重复条目的 np.arrays 列表。
谢谢 :)
numpy.unique
已经非常优化,除非您对基础数据有所了解,否则您不太可能获得比现有数据更快的速度。例如,如果数据都是您可以使用的小整数,numpy.bincount
或者如果每个数组中的唯一值基本相同,则可以对整个数组列表进行一些优化。
pandas.unique()
比 快得多numpy.unique()
。Pandas 版本不对结果进行排序,但您可以自己进行排序,如果结果比输入小得多(即有很多重复值),它仍然会快得多:
np.sort(pd.unique(arr))
时间:
In [1]: x = np.random.randint(10, 20, 50000000)
In [2]: %timeit np.sort(pd.unique(x))
201 ms ± 9.32 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [3]: %timeit np.unique(x)
1.49 s ± 27.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我还查看list(set())
了列表中的和字符串,介于熊猫系列和 python 列表之间。
data = np.random.randint(0,10,100)
data_hex = [str(hex(n)) for n in data] # just some simple strings
sample1 = pd.Series(data, name='data')
sample2 = data.tolist()
sample3 = pd.Series(data_hex, name='data')
sample4 = data_hex
然后是基准:
%timeit np.unique(sample1) # 16.4 µs ± 464 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit np.unique(sample2) # 15.9 µs ± 743 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit np.unique(sample3) # 45.8 µs ± 5.88 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit np.unique(sample4) # 20.6 µs ± 680 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit pd.unique(sample1) # 60.3 µs ± 5.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit pd.unique(sample2) # 196 µs ± 18.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit pd.unique(sample3) # 79.7 µs ± 3.98 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit pd.unique(sample4) # 214 µs ± 61 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each
%timeit list(set(sample1)) # 16.3 µs ± 1.63 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit list(set(sample2)) # 1.64 µs ± 83.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit list(set(sample3)) # 17.8 µs ± 1.96 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit list(set(sample4)) # 2.48 µs ± 439 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
要点是:
从带有整数的 Pandas 系列开始?要么选择np.unique()
要么list(set())
从带字符串的 Pandas 系列开始?一起去list(set())
从整数列表开始?一起去list(set())
从字符串列表开始?一起去list(set())
但是,如果 N=1,000,000 而不是,结果会有所不同。
%timeit np.unique(sample1) # 26.5 ms ± 616 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.unique(sample2) # 98.1 ms ± 3.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit np.unique(sample3) # 1.31 s ± 78.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit np.unique(sample4) # 174 ms ± 2.57 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit pd.unique(sample1) # 10.5 ms ± 472 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit pd.unique(sample2) # 99.3 ms ± 5.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit pd.unique(sample3) # 46.4 ms ± 4.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit pd.unique(sample4) # 113 ms ± 11.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(set(sample1)) # 25.9 ms ± 2.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(set(sample2)) # 11.2 ms ± 496 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit list(set(sample3)) # 37.1 ms ± 1.28 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit list(set(sample4)) # 20.2 ms ± 843 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
从带有整数的 Pandas 系列开始?一起去pd.unique()
从带字符串的 Pandas 系列开始?一起去list(set())
从整数列表开始?一起去list(set())
从字符串列表开始?一起去list(set())
以下是一些基准:
In [72]: ar_list = [np.random.randint(0, 100, 1000) for _ in range(100)]
In [73]: %timeit map(np.unique, ar_list)
100 loops, best of 3: 4.9 ms per loop
In [74]: %timeit [np.unique(ar) for ar in ar_list]
100 loops, best of 3: 4.9 ms per loop
In [75]: %timeit [pd.unique(ar) for ar in ar_list] # using pandas
100 loops, best of 3: 2.25 ms per loop
所以pandas.unique
似乎比numpy.unique
. 然而,文档字符串提到这些值“不一定是排序的”,这(部分)解释了它更快。在此示例中使用列表推导或map
没有区别。
numpy.unique()
是基于排序(quicksort
),而是pandas.unique()
基于哈希表。通常,根据我的基准,后者更快。它们已经非常优化。对于一些特殊情况,可以继续优化性能。例如,如果数据已经排序,则可以跳过排序方法:
# ar is already sorted
# this segment is from source code of numpy
mask = np.empty(ar.shape, dtype=np.bool_)
mask[:1] = True
mask[1:] = ar[1:] != ar[:-1]
ret = ar[mask]
我遇到了和你类似的问题。我写了我的unique
函数供我使用。因为pandas.unique
不支持return_counts
选项。这是快速实施。但我的实现只支持整数数组。您可以在此处查看源代码。