我有一个pandas数据帧如下:
time winner loser stat
1 A B 0
2 C B 0
3 D B 1
4 E B 0
5 F A 0
6 G A 0
7 H A 0
8 I A 1
每一行都是匹配结果。第一列是比赛时间,第二列和第三列包含赢家/输家,第四列是比赛中的一个数据。
我想检测每个输家的统计数据为零。
预期结果应如下所示:
time winner loser stat streak
1 A B 0 1
2 C B 0 2
3 D B 1 0
4 E B 0 1
5 F A 0 1
6 G A 0 2
7 H A 0 3
8 I A 1 0
在伪代码中,算法应该像这样工作:
.groupby
loser
列。 loser
组stat
列:如果它包含0
,则将streak
值从上一行增加0
。如果不是0
,则启动新的streak
,即将0
放入streak
列。所以.groupby
很清楚。但是,我需要某种.apply
,我可以看看上一行?这就是我被困住的地方。
答案 0 :(得分:13)
您可以apply
自定义函数f
,然后cumsum
,cumcount
和astype
:
def f(x):
x['streak'] = x.groupby( (x['stat'] != 0).cumsum()).cumcount() +
( (x['stat'] != 0).cumsum() == 0).astype(int)
return x
df = df.groupby('loser', sort=False).apply(f)
print df
time winner loser stat streak
0 1 A B 0 1
1 2 C B 0 2
2 3 D B 1 0
3 4 E B 0 1
4 5 F A 0 1
5 6 G A 0 2
6 7 H A 0 3
7 8 I A 1 0
为了更好的未成年:
def f(x):
x['c'] = (x['stat'] != 0).cumsum()
x['a'] = (x['c'] == 0).astype(int)
x['b'] = x.groupby( 'c' ).cumcount()
x['streak'] = x.groupby( 'c' ).cumcount() + x['a']
return x
df = df.groupby('loser', sort=False).apply(f)
print df
time winner loser stat c a b streak
0 1 A B 0 0 1 0 1
1 2 C B 0 0 1 1 2
2 3 D B 1 1 0 0 0
3 4 E B 0 1 0 1 1
4 5 F A 0 0 1 0 1
5 6 G A 0 0 1 1 2
6 7 H A 0 0 1 2 3
7 8 I A 1 1 0 0 0
答案 1 :(得分:4)
不像jezrael的answer那么优雅,但对我来说更容易理解......
首先,定义一个适用于单个输家的函数:
def f(df):
df['streak2'] = (df['stat'] == 0).cumsum()
df['cumsum'] = np.nan
df.loc[df['stat'] == 1, 'cumsum'] = df['streak2']
df['cumsum'] = df['cumsum'].fillna(method='ffill')
df['cumsum'] = df['cumsum'].fillna(0)
df['streak'] = df['streak2'] - df['cumsum']
df.drop(['streak2', 'cumsum'], axis=1, inplace=True)
return df
条纹本质上是cumsum
,但我们需要在每次stat
为1时重置它。因此,我们减去cumsum
的值,其中stat
为1 ,继续推进到下一个。
然后groupby
和apply
由输家:
df.groupby('loser').apply(f)
结果与预期一致。
答案 2 :(得分:3)
您可以使用iterrows
访问上一行:
df['streak'] = 0
for i, row in df.iterrows():
if i != 0:
if row['stat'] == 0:
if row['loser'] == df.ix[i-1, 'loser']:
df.ix[i, 'streak'] = df.ix[i-1, 'streak'] + 1
else:
df.ix[i, 'streak'] = 1
else:
if row['stat'] == 0:
df.ix[i, 'streak'] = 1
给出了:
In [210]: df
Out[210]:
time winner loser stat streak
0 1 A B 0 1
1 2 C B 0 2
2 3 D B 1 0
3 4 E B 0 1
4 5 F A 0 1
5 6 G A 0 2
6 7 H A 0 3
7 8 I A 1 0