Python pandas 每次出现 0 时重置的 cumsum
Python pandas cumsum with reset everytime there is a 0
我有一个包含 0 和 1 的矩阵,我想对每一列执行 cumsum,只要观察到零,它就会重置为 0。例如,如果我们有以下内容:
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
print(df)
a b
0 0 1
1 1 1
2 0 1
3 1 0
4 1 1
5 0 1
我想要的结果是:
print(df)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
然而,当我尝试 df.cumsum() * df
时,我能够正确识别 0 元素,但计数器没有重置:
print(df.cumsum() * df)
a b
0 0 1
1 1 2
2 0 3
3 2 0
4 3 4
5 0 5
试试这个
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
df['groupId1']=df.a.eq(0).cumsum()
df['groupId2']=df.b.eq(0).cumsum()
New=pd.DataFrame()
New['a']=df.groupby('groupId1').a.transform('cumsum')
New['b']=df.groupby('groupId2').b.transform('cumsum')
New
Out[1184]:
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
您可以使用:
a = df != 0
df1 = a.cumsum()-a.cumsum().where(~a).ffill().fillna(0).astype(int)
print (df1)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
一个有点老套的方法是在执行 cumsum
:
之前识别零的索引并将相应的值设置为这些索引的负数
import pandas as pd
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
z = np.where(df['b']==0)
df['b'][z[0]] = -z[0]
df['b'] = np.cumsum(df['b'])
df
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 1 1
5 0 2
您也可以尝试以下简单但可靠的方法。
每列 - 创建要在其中计数的组。一旦出现按行的顺序值差异,组就开始,并在值保持不变时持续:(x != x.shift()).cumsum()
.
示例:
a b
0 1 1
1 2 1
2 3 1
3 4 2
4 4 3
5 5 3
使用 pd.DataFrame
的 apply
和 groupby
方法计算每列组内的累积总和,您将在一行中获得零重置的累积总和:
import pandas as pd
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
cs = df.apply(lambda x: x.groupby((x != x.shift()).cumsum()).cumsum())
print(cs)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
我有一个包含 0 和 1 的矩阵,我想对每一列执行 cumsum,只要观察到零,它就会重置为 0。例如,如果我们有以下内容:
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
print(df)
a b
0 0 1
1 1 1
2 0 1
3 1 0
4 1 1
5 0 1
我想要的结果是:
print(df)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
然而,当我尝试 df.cumsum() * df
时,我能够正确识别 0 元素,但计数器没有重置:
print(df.cumsum() * df)
a b
0 0 1
1 1 2
2 0 3
3 2 0
4 3 4
5 0 5
试试这个
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
df['groupId1']=df.a.eq(0).cumsum()
df['groupId2']=df.b.eq(0).cumsum()
New=pd.DataFrame()
New['a']=df.groupby('groupId1').a.transform('cumsum')
New['b']=df.groupby('groupId2').b.transform('cumsum')
New
Out[1184]:
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
您可以使用:
a = df != 0
df1 = a.cumsum()-a.cumsum().where(~a).ffill().fillna(0).astype(int)
print (df1)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2
一个有点老套的方法是在执行 cumsum
:
import pandas as pd
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
z = np.where(df['b']==0)
df['b'][z[0]] = -z[0]
df['b'] = np.cumsum(df['b'])
df
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 1 1
5 0 2
您也可以尝试以下简单但可靠的方法。
每列 - 创建要在其中计数的组。一旦出现按行的顺序值差异,组就开始,并在值保持不变时持续:(x != x.shift()).cumsum()
.
示例:
a b
0 1 1
1 2 1
2 3 1
3 4 2
4 4 3
5 5 3
使用 pd.DataFrame
的 apply
和 groupby
方法计算每列组内的累积总和,您将在一行中获得零重置的累积总和:
import pandas as pd
df = pd.DataFrame([[0,1],[1,1],[0,1],[1,0],[1,1],[0,1]],columns = ['a','b'])
cs = df.apply(lambda x: x.groupby((x != x.shift()).cumsum()).cumsum())
print(cs)
a b
0 0 1
1 1 2
2 0 3
3 1 0
4 2 1
5 0 2