2016-06-17 133 views
6

我有一個帶有布爾列的pandas DataFrame,按另一列排序,需要計算反向累積和,也就是從當前行到底部的真值的數量。pandas.DataFrame中一列的反向累加和

In [13]: df = pd.DataFrame({'A': [True] * 3 + [False] * 5, 'B': np.random.rand(8) }) 

In [15]: df = df.sort_values('B') 

In [16]: df 
Out[16]: 
     A   B 
6 False 0.037710 
2 True 0.315414 
4 False 0.332480 
7 False 0.445505 
3 False 0.580156 
1 True 0.741551 
5 False 0.796944 
0 True 0.817563 

我需要的東西,這將使我有值的新列

3 
3 
2 
2 
2 
2 
1 
1 

也就是說,它應該包含該行及以下行真值的數量每行。

我已經嘗試過使用.iloc[::-1]的各種方法,但結果並非如此。

想想,我錯過了一些明顯的事情。我昨天才開始使用熊貓。

回答

10

反向列A,採取cumsum,然後再反向:

df['C'] = df.ix[::-1, 'A'].cumsum()[::-1] 

import pandas as pd 
df = pd.DataFrame(
    {'A': [False, True, False, False, False, True, False, True], 
    'B': [0.03771, 0.315414, 0.33248, 0.445505, 0.580156, 0.741551, 0.796944, 0.817563],}, 
    index=[6, 2, 4, 7, 3, 1, 5, 0]) 
df['C'] = df.ix[::-1, 'A'].cumsum()[::-1] 
print(df) 

產量

 A   B C 
6 False 0.037710 3 
2 True 0.315414 3 
4 False 0.332480 2 
7 False 0.445505 2 
3 False 0.580156 2 
1 True 0.741551 2 
5 False 0.796944 1 
0 True 0.817563 1 

或者,你可以指望的True S中的數列A和減法t(移位)cumsum:

In [113]: df['A'].sum()-df['A'].shift(1).fillna(0).cumsum() 
Out[113]: 
6 3 
2 3 
4 2 
7 2 
3 2 
1 2 
5 1 
0 1 
Name: A, dtype: object 

但是,這是顯着較慢。使用IPython執行基準:

In [116]: df = pd.DataFrame({'A':np.random.randint(2, size=10**5).astype(bool)}) 

In [117]: %timeit df['A'].sum()-df['A'].shift(1).fillna(0).cumsum() 
10 loops, best of 3: 19.8 ms per loop 

In [118]: %timeit df.ix[::-1, 'A'].cumsum()[::-1] 
1000 loops, best of 3: 701 µs per loop 
0

這工作,但速度很慢...像@unutbu答案。真正解決爲1.雖然失敗,或者任何其他值。

df[2] = df.groupby('A').cumcount(ascending=False)+1 
df[1] = np.where(df['A']==True,df[2],None) 
df[1] = df[1].fillna(method='bfill').fillna(0) 
del df[2] 

     A   B 1 
# 3 False 0.277557 3.0 
# 7 False 0.400751 3.0 
# 6 False 0.431587 3.0 
# 5 False 0.481006 3.0 
# 1 True 0.534364 3.0 
# 2 True 0.556378 2.0 
# 0 True 0.863192 1.0 
# 4 False 0.916247 0.0