Matlab的accumarray的Python转录

时间:2019-04-25 18:29:24

标签: python pandas matlab numpy scipy

我想得到与Python中Matlab的accumarray函数相同的结果。我知道还有其他一些讨论可以为这个问题提供解决方案,但我认为这种情况似乎更加困难。

它对应于this Matlab script的情况,其中包含以下行:

binned_data = accumarray(bins(all(bins>0,2),:),1/nrows,M(ones(1,ncols)));

我试图通过阅读the official documentation of accumarray来理解这种计算的含义,但是对我来说还不清楚。

您了解这一行的含义,并且知道如何通过某些Python库(numpy,scipy,pandas等)获得相同的结果吗?

编辑:据我了解,我的问题与this one不同。如您所见,在我的案例中,accumarray有3个输入参数,而其他讨论中的示例中只有2个输入参数。此外,在其他讨论中未提供使用accumarray的示例:对该函数的引用仅出现在标题中(作者仅给出了对该函数的非常严格的定义)。就我而言,有一个实际的例子似乎比其他讨论中考虑的例子更笼统。

1 个答案:

答案 0 :(得分:0)

我并未对所有细节进行测试,但是此功能应该是您所需要的。它可以处理Matlab函数要做的几件事。

def accumarray(subs, vals, size=None, fun=np.sum):

    if len(subs.shape) == 1:
        if size is None:
            size = [subs.values.max() + 1, 0]

        acc = val.groupby(subs).agg(fun)
    else:
        if size is None:
            size = [subs.values.max()+1, subs.shape[1]]

        subs = subs.copy().reset_index()
        by = subs.columns.tolist()[1:]
        acc = subs.groupby(by=by)['index'].agg(list).apply(lambda x: val[x].agg(fun))
        acc = acc.to_frame().reset_index().pivot_table(index=0, columns=1, aggfunc='first')
        acc.columns = range(acc.shape[1])
        acc = acc.reindex(range(size[1]), axis=1).fillna(0)

    id_x = range(size[0])
    acc = acc.reindex(id_x).fillna(0)

    return acc

您可以进行简单的计算,例如:

val = pd.Series(np.arange(101, 106+1))
subs = pd.Series([1, 3, 4, 3, 4]) - 1
accumarray(subs, val)

或更复杂的东西,例如:

val = pd.Series(np.arange(101, 106+1))
subs = (pd.DataFrame([[1, 1], [2, 2], [3, 2], [1, 1], [2, 2], [4, 1]]) - 1)
accumarray(subs,val, [4, 4])

val = pd.Series(range(1, 10+1))
subs = pd.DataFrame([[1, 1], [1, 1], [1, 1], [1, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 1], [2, 2]]) - 1
accumarray(subs, val, None, list)