def _cumsum(group_idx, a, size, fill_value=None, dtype=None):
    """
    N to N aggregate operation of cumsum. Perform cumulative sum for each group.

    group_idx = np.array([4, 3, 3, 4, 4, 1, 1, 1, 7, 8, 7, 4, 3, 3, 1, 1])
    a = np.array([3, 4, 1, 3, 9, 9, 6, 7, 7, 0, 8, 2, 1, 8, 9, 8])
    _cumsum(group_idx, a, np.max(group_idx) + 1)
    >>> array([ 3,  4,  5,  6, 15,  9, 15, 22,  7,  0, 15, 17,  6, 14, 31, 39])
    """
    sortidx = np.argsort(group_idx, kind='mergesort')
    invsortidx = np.argsort(sortidx, kind='mergesort')
    group_idx_srt = group_idx[sortidx]

    a_srt = a[sortidx]
    a_srt_cumsum = np.cumsum(a_srt, dtype=dtype)

    increasing = np.arange(len(a), dtype=int)
    group_starts = _min(group_idx_srt, increasing, size, fill_value=0)[group_idx_srt]
    a_srt_cumsum += -a_srt_cumsum[group_starts] + a_srt[group_starts]
    return a_srt_cumsum[invsortidx]
def _cumsum ( group_idx , a , size , fill_value = None , dtype = None ) : sortidx = np . argsort ( group_idx , kind = 'mergesort' ) invsortidx = np . argsort ( sortidx , kind = 'mergesort' ) group_idx_srt = group_idx [ sortidx ] a_srt = a [ sortidx ] a_srt_cumsum = np . cumsum ( a_srt , dtype = dtype ) increasing = np . arange ( len ( a ) , dtype = int ) group_starts = _min ( group_idx_srt , increasing , size , fill_value = 0 ) [ group_idx_srt ] a_srt_cumsum += - a_srt_cumsum [ group_starts ] + a_srt [ group_starts ] return a_srt_cumsum [ invsortidx ]
N to N aggregate operation of cumsum. Perform cumulative sum for each group.

    group_idx = np.array([4, 3, 3, 4, 4, 1, 1, 1, 7, 8, 7, 4, 3, 3, 1, 1])
    a = np.array([3, 4, 1, 3, 9, 9, 6, 7, 7, 0, 8, 2, 1, 8, 9, 8])
    _cumsum(group_idx, a, np.max(group_idx) + 1)
    >>> array([ 3,  4,  5,  6, 15,  9, 15, 22,  7,  0, 15, 17,  6, 14, 31, 39])