簡體   English   中英

在熊貓數據框中找到條紋

[英]finding streaks in pandas dataframe

我有一個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 ,我可以看看前一行? 這是我被困的地方。

您可以apply自定義函數f ,然后應用cumsumcumcountastype

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

不像jezrael的答案那么優雅,但對我來說更容易理解......

首先,定義一個與單個輸家一起使用的函數:

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時重置它。因此我們減去stat為1的cumsum的值,結轉到下一個1。

然后groupby並通過輸家apply

df.groupby('loser').apply(f)

結果如預期。

您可以使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM