条件下累计和重置

时间:2017-09-30 15:22:28

标签: python pandas

我有一个与此类似的数据框:

df = pd.DataFrame({'col1': ['a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'c'],
                 'col2': [1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2],
                 'col3': [1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0],
                 'desired': [0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1]})

我想在col3上应用滚动总和,当col1col2更改或col3变为零时,该值会重置。

请注意,总和偏移1个单元格。这意味着新(col1, col2)组合的期望值将始终为零。

下面的代码演示了所需的逻辑。但是,下面的数据集需要将近4分钟。

des = []
count = 0
for i in range(1, len(df)):
    des.append(count)
    if (df.iloc[i-1].col1 == df.iloc[i].col1) & \
       (df.iloc[i-1].col2 == df.iloc[i].col2) & \
       (df.iloc[i-1].col3 == 1):

        count += 1
    else:
        count = 0

des.append(0)

df['desired'] = des

要测试的更大数据集:https://www.dropbox.com/s/hbafcq6hdkh4r9r/test.csv?dl=0

2 个答案:

答案 0 :(得分:2)

首先使用io.emit() shift,然后连续计算groupby

1

答案 1 :(得分:1)

由于OP希望获得 rolling (滚动)计数,因此这似乎表明他们希望处理可能在df中不同位置重复的小组,而又不希望将所有小组混在一起(例如groupby可以。)

在问题陈述中,听起来更像是带有复位的累积操作。这是一类相对容易矢量化的问题,根本不涉及groupby

这是使用numpy的一种方式:

def cum_count(df, groupcols, zerocol):
    a = df[groupcols].values
    c = df[zerocol].values
    # find indices to reset the cumulative count
    r0 = np.concatenate(([True], np.any(a[1:] != a[:-1], axis=1)))
    r1 = np.concatenate(([True], c[:-1] == 0))
    reset = np.nonzero(r0 + r1)[0]
    # offset: values to subtract at reset indices
    off = np.concatenate(([0], np.diff(reset)))
    # we add 1 everywhere except at reset indices
    delt = np.ones(df.shape[0], dtype=int)
    delt[reset] -= off

    return np.cumsum(delt) - 1

这是一个极端的例子:

df = pd.DataFrame([
    ['a', 1, 1, 0],
    ['a', 1, 1, 1],
    ['a', 1, 1, 2],
    ['b', 1, 1, 0],
    ['b', 1, 1, 1],
    ['b', 1, 1, 2],
    ['a', 1, 1, 0],
    ['a', 1, 1, 1],
    ['a', 1, 1, 2],
], columns='col1 col2 col3 desired'.split())

c = custom_cum_count(df, 'col1 col2'.split(), 'col3')
assert np.all(c == df['desired'])
print(c)

# out
[0 1 2 0 1 2 0 1 2]