numpy 中的累积模式

Cumulative Mode in numpy

我想在 numpy 中有效地计算沿轴的累积模式。

例如

>>> arr = np.random.RandomState(3).randint(3, size = (2, 5))
>>> arr
array([[2, 0, 1, 0, 0],
       [0, 1, 1, 2, 1]])
>>> assert np.array_equal(cummode(arr, axis = 1), [[2,2,2,0,0],[0,0,1,1,1])

有没有有效的方法来做到这一点?我想它可以通过返回第一个数字来达到给定计数来处理平局。

好的,它不是完全通用的,因为它不能沿任何轴工作,但现在我已经制作了一个可以使用 scipy-weave 的版本。

from scipy import weave

def cummode(x, axis = 1):

    assert x.ndim == 2 and axis == 1, 'Only implemented for a special case!'
    all_values, element_ids = np.unique(x, return_inverse=True)
    n_unique = len(all_values)
    element_ids = element_ids.reshape(x.shape)
    result = np.zeros(x.shape, dtype = int)
    counts = np.zeros(n_unique, dtype = int)
    code = """
    int n_samples = Nelement_ids[0];
    int n_events = Nelement_ids[1];
    for (int i=0; i<n_samples; i++){
        int maxcount = 0;
        int maxel = -1;

        for (int k=0; k<n_unique; k++)
            counts[k] = 0;

        for (int j=0; j<n_events; j++){
            int ix = i*n_events+j;
            int k = element_ids[ix];
            counts[k]+=1;
            if (counts[k] > maxcount){
                maxcount = counts[k];
                maxel = k;
            }
            result[ix]=maxel;
        }
    }
    """
    weave.inline(code, ['element_ids', 'result', 'n_unique', 'counts'], compiler = 'gcc')
    mode_values = all_values[result]
    return mode_values

这是一个纯 Python 函数,可用于列表或任何可迭代对象:

from collections import defaultdict

def cummode(alist):
    dd = defaultdict(int)
    mode = [(None,0)]
    for i in alist:
        dd[i] += 1
        if dd[i]>mode[-1][1]:
            newmode = (i,dd[i])
        else:
            newmode = mode[-1]
        mode.append(newmode)
    mode.pop(0)
    return mode, dd

mode,dd = cummode([0,1,3,6,1,2,3,3,2,1,10,0])
print(dd)
print(mode)

对于测试用例,产生

defaultdict(<type 'int'>, {0: 2, 1: 3, 2: 2, 3: 3, 6: 1, 10: 1})
[(0, 1), (0, 1), (0, 1), (0, 1), (1, 2), (1, 2), (1, 2), (3, 3), (3, 3), (3, 3), (3, 3), (3, 3)]

A detaultdict 是一种在您事先不知道所有键时累积值的干净快速的方法。对于小型列表和数组,它可能胜过基于 numpy 的版本,即使使用 weave,只是因为它不会产生创建数组的开销。但是对于大的,它可能会滞后。另外,我还没有将其概括为处理多个值(行)。