2016-06-17 37 views
6

Tôi có một khung dữ liệu DataFrame với cột boolean, được sắp xếp theo cột khác và cần tính tổng tích lũy ngược, nghĩa là số lượng giá trị thực từ hàng hiện tại xuống dưới.Tổng tích lũy đảo ngược của một cột trong pandas.DataFrame

Ví dụ

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 

tôi cần cái gì đó sẽ cho tôi một cột mới với các giá trị

3 
3 
2 
2 
2 
2 
1 
1 

Đó là, cho mỗi hàng nó nên chứa lượng giá trị Đúng vào hàng này và các hàng bên dưới .

Tôi đã thử các phương pháp khác nhau bằng cách sử dụng .iloc[::-1] nhưng kết quả không phải là điều mong muốn.

Hãy suy nghĩ, tôi thiếu một số điều hiển nhiên. Tôi đã bắt đầu sử dụng Pandas chỉ ngày hôm qua.

Trả lời

10

Xếp cột A, đi cumsum, sau đó đảo ngược lại:

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) 

sản lượng

 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 

Ngoài ra, bạn có thể đếm số True s trong cột A và subtrac t the (shifted) 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 

Nhưng điều này chậm hơn đáng kể. Sử dụng IPython để thực hiện điểm chuẩn:

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

Tác phẩm này nhưng chậm ... như @unutbu answer. True giải quyết đến 1. Fails trên False, hoặc bất kỳ giá trị khác mặc dù.

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 
Các vấn đề liên quan