【问题标题】:What are some fast implementations of a "nunique" for numpy with a max count threshold?具有最大计数阈值的 numpy 的“nunique”有哪些快速实现?
【发布时间】:2021-09-15 18:06:07
【问题描述】:

我确定这在其他域中有一个名称(也许大约不同?)。

假设您想计算一个 numpy 数组中不同元素的数量,但您只关心低于某个阈值的数字,高于该阈值的数字,您只需返回它有多个 thresh 唯一条目。这对于您不关心有 10000 个条目只是可能有超过 10 个条目的高数量数组特别有用。

在编译语言中,这很容易快速实现。但是有哪些快速的实现暴露给 python?

天真的人可能会像这样尝试 numba:

@numba.jit(nopython=True)
def nunique_max_thresh(x, thresh=10):
    seen = set()
    for i in range(len(x)):
        seen.add(x[i])
        if len(seen) > thresh:
            return thresh
    return len(seen)

但不支持set 用法。

Cython 是一个选项,但我想知道这是否已经在某些库或 python 的其他地方完成。似乎瓶颈会做这种事情,但实际上并不存在。

https://bottleneck.readthedocs.io/en/latest/reference.html

例如,考虑这些类型的数组:

import string                                                                                                                                                                                              
import numpy as np
np.random.seed(0)                                                                                                                                                                                         
a = np.random.choice(list(string.ascii_letters), 1e7)
b = np.ones(int(1e7))

您只想知道这个数组是否有 10 个或更多的唯一值。不要使用这些是长度为一的字符串这一事实。

作为参考,这个运行。但可能不是最优的。

import numpy as np
cimport numpy as np

def nunique_truncated(np.ndarray x_in, np.int thresh=10):
    seen = set()
    for i in range(x_in.shape[0]):
        seen.add(x_in[i])
        if len(seen) >= thresh:
            return thresh

【问题讨论】:

  • a) 如果这是用于 NLP 字数统计,则使用计数矢量化器来抑制停用词、映射标点符号和大小写 b) Bloom filters 存在
  • @smci 情况并非如此。我实际上只是在处理具有大量对象列的数据框。显然,如果它们是 pandas 分类,所有工作都已经完成。如果您想决定是否应以 dict/categorical 格式存储列,则会出现此类问题。
  • pandas 包装 numpy 并在 Series 和 DataFrames 上有效地实现 uniquenunique。我建议这是你想要的。如果您仍然不喜欢它的性能,请以您正在谈论的任何规模发布一个易于处理的示例 (minimal reproducible example)。种子随机数据(例如自动生成的字符串)很好。顺便说一句,熊猫处理分类很好。除非您提供 MCVE 示例,否则此问题可能会被关闭为“寻求算法/pkg 建议”。
  • @mathtick: 不,K=1 是一个糟糕的测试选择,因为集合中只有 26 个元素,而且它们几乎都适合零内存,不像说 26^K 对于 K = 3 或 4。
  • Numba 支持 Set,但数据类型 'a=a.view(np.int32)。

标签: python numpy unique distinct distinct-values


【解决方案1】:

正如@hpaulj 建议的那样,您可以只使用numba 而没有 set 或dict,这应该是合理的,因为该用例专门针对较短的列表。显然,某些制度会因包含查找缓慢而受到影响。

import numba
        
@numba.jit(nopython=True)
def nunique_truncated_numba(x_in, thresh=10):                                                            
    seen = list()
    for i, x in enumerate(x_in):
        if x not in seen:
            seen.append(x)                                                                                   
        if len(seen) > thresh:                                                                           
            return len(seen)                                                                             
    return len(seen)

hard 的情况确实是当您没有达到阈值时(您正在使用 python 进行矢量化扫描)。

In [6]: %timeit cud.nunique_truncated(b)                                                                                                                                                                           
116 µs ± 304 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [7]: %timeit len(np.unique(b))                                                                                                                                                                                  
1.26 ms ± 2.64 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

如果有人有其他建议和技巧会很感兴趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 2018-10-07
    • 1970-01-01
    • 2014-02-17
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 2018-04-21
    相关资源
    最近更新 更多