我对python比较陌生。
我尝试为每个客户端计算累积总和,以查看相应的不事件月份(标志:1 或 0)。因此,当我们有一个 0 时,需要重置 1 的累积总和。当我们有一个新客户时,也需要重置。请参见下面的示例,其中 a 是客户列,b 是日期。

经过一些研究,我发现了问题“Cumsum reset at NaN”和“In Python Pandas using cumsum with groupby”。我想我有点需要把它们放在一起。
将 'Cumsum reset at NaN' 的代码调整为向 0 的重置是成功的:

cumsum = v.cumsum().fillna(method='pad')
reset = -cumsum[v.isnull() !=0].diff().fillna(cumsum)
result = v.where(v.notnull(), reset).cumsum()

但是,我没有成功添加 groupby。我的数还在继续……

因此,数据集将是这样的:
将 Pandas 导入为 pd
df =  pd.DataFrame({'a' : [1,1,1,1,1,1,1,2,2,2,2,2,2,2],
                    'b' : [1/15,2/15,3/15,4/15,5/15,6/15,1/15,2/15,3/15,4/15,5/15,6/15],
                    'c' : [1,0,1,0,1,1,0,1,1,0,1,1,1,1]})

这应该会产生一个包含 a、b、c 和 d 列的数据框
'd' : [1,0,1,0,1,2,0,1,2,0,1,2,3,4]

请注意,我有一个非常大的数据集,因此计算时间非常重要。

感谢你们对我的帮助

最佳答案

在组中找到连续值后使用 groupby.apply cumsum 。然后 groupby.cumcount 将整数计数到每个连续值,然后加 1。

与原始行相乘以创建取消所有零并仅考虑正值的 AND 逻辑。

df['d'] = df.groupby('a')['c']                                                            \
            .apply(lambda x: x * (x.groupby((x != x.shift()).cumsum()).cumcount() + 1))

print(df['d'])

0     1
1     0
2     1
3     0
4     1
5     2
6     0
7     1
8     2
9     0
10    1
11    2
12    3
13    4
Name: d, dtype: int64

另一种做法是在 groupby 对象上的 series.expanding 之后应用一个函数,该函数基本上计算从第一个索引到当前索引的系列的值。

稍后使用 reduce 将两个 args 的函数累积应用于 iterable 的项目,以将其减少为单个值。
from functools import reduce

df.groupby('a')['c'].expanding()                                         \
  .apply(lambda i: reduce(lambda x, y: x+1 if y==1 else 0, i, 0))

a
1  0     1.0
   1     0.0
   2     1.0
   3     0.0
   4     1.0
   5     2.0
   6     0.0
2  7     1.0
   8     2.0
   9     0.0
   10    1.0
   11    2.0
   12    3.0
   13    4.0
Name: c, dtype: float64

时间:
%%timeit
df.groupby('a')['c'].apply(lambda x: x * (x.groupby((x != x.shift()).cumsum()).cumcount() + 1))
100 loops, best of 3: 3.35 ms per loop

%%timeit
df.groupby('a')['c'].expanding().apply(lambda s: reduce(lambda x, y: x+1 if y==1 else 0, s, 0))
1000 loops, best of 3: 1.63 ms per loop

关于python-3.x - 在 Python Pandas 中使用 cumsum 和 groupby 并在值为 0 时重置 cumsum,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39741136/

10-13 05:20