2017-02-22 91 views
5

由于DF来计算大熊猫条纹Python的方式数据帧

df = pd.DataFrame([[1, 5, 2, 8, 2], [2, 4, 4, 20, 2], [3, 3, 1, 20, 2], [4, 2, 2, 1, 3], [5, 1, 4, -5, -4], [1, 5, 2, 2, -20], 
       [2, 4, 4, 3, -8], [3, 3, 1, -1, -1], [4, 2, 2, 0, 12], [5, 1, 4, 20, -2]], 
      columns=['A', 'B', 'C', 'D', 'E'], index=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 

基于this answer,我创建了一个函数来计算条纹(上,下)。

def streaks(df, column): 
    #Create sign column 
    df['sign'] = 0 
    df.loc[df[column] > 0, 'sign'] = 1 
    df.loc[df[column] < 0, 'sign'] = 0 
    # Downstreak 
    df['d_streak2'] = (df['sign'] == 0).cumsum() 
    df['cumsum'] = np.nan 
    df.loc[df['sign'] == 1, 'cumsum'] = df['d_streak2'] 
    df['cumsum'] = df['cumsum'].fillna(method='ffill') 
    df['cumsum'] = df['cumsum'].fillna(0) 
    df['d_streak'] = df['d_streak2'] - df['cumsum'] 
    df.drop(['d_streak2', 'cumsum'], axis=1, inplace=True) 
    # Upstreak 
    df['u_streak2'] = (df['sign'] == 1).cumsum() 
    df['cumsum'] = np.nan 
    df.loc[df['sign'] == 0, 'cumsum'] = df['u_streak2'] 
    df['cumsum'] = df['cumsum'].fillna(method='ffill') 
    df['cumsum'] = df['cumsum'].fillna(0) 
    df['u_streak'] = df['u_streak2'] - df['cumsum'] 
    df.drop(['u_streak2', 'cumsum'], axis=1, inplace=True) 
    del df['sign'] 
    return df 

该功能运行良好,但是很长。我敢肯定,写这篇文章有更好的方法。我尝试了其他答案,但效果不佳。

这是所需的输出

streaks(df, 'E') 


    A B C D  E d_streak u_streak 
1 1 5 2 8  2   0.0 1.0 
2 2 4 4 20  2   0.0 2.0 
3 3 3 1 20  2   0.0 3.0 
4 4 2 2 1  3   0.0 4.0 
5 5 1 4 -5 -4   1.0 0.0 
6 1 5 2 2 -20   2.0 0.0 
7 2 4 4 3 -8   3.0 0.0 
8 3 3 1 -1 -1   4.0 0.0 
9 4 2 2 0 12   0.0 1.0 
10 5 1 4 20 -2   1.0 0.0 
+0

你能解释一下这个实现吗? – Divakar

+0

@Divakar该函数计算> 0和<0的值序列,并保持运行总数的积分,一旦序列结束,它将重置。 – hernanavella

+0

如果有'value == 0'会怎么样? – Divakar

回答

6

你可以简化函数,如下所示:

def streaks(df, col): 
    sign = np.sign(df[col]) 
    s = sign.groupby((sign!=sign.shift()).cumsum()).cumsum() 
    return df.assign(u_streak=s.where(s>0, 0.0), d_streak=s.where(s<0, 0.0).abs()) 

使用它:

streaks(df, 'E') 

enter image description here


首先,使用np.sign来计算所考虑列中存在的每个单元格的符号。这些将+1分配给正数,将-1分配给负数。

接下来,使用sign!=sign.shift()来标识相邻值的集合(比较当前单元格和下一个单元格),并将其用于分组过程中的累计总和。

执行groupby让这些作为关键/条件,并再次取得跨子组元素的累计和。

最后,将计算得到的cumsum的值分别计算为ustreak和负计算值(取其模数后的绝对值)为dstreak