2012-12-27 57 views
29

Tôi đang cố nhân hai cột hiện có trong một khung quảng cáo gấu trúc (orders_df) - Giá (giá đóng cổ phiếu) và Số lượng (số lượng chứng khoán) và thêm phép tính vào cột mới có tên 'Giá trị'. Vì một số lý do khi tôi chạy mã này, tất cả các hàng trong cột 'Giá trị' là số dương, trong khi một số hàng phải là số âm. Trong cột Hành động trong DataFrame có bảy hàng có chuỗi 'Bán' và bảy hàng có chuỗi 'Mua'.Tôi muốn nhân hai cột trong một DataFrame gấu trúc và thêm kết quả vào một cột mới

for i in orders_df.Action: 
if i == 'Sell': 
    orders_df['Value'] = orders_df.Prices*orders_df.Amount 
elif i == 'Buy': 
    orders_df['Value'] = -orders_df.Prices*orders_df.Amount) 

Vui lòng cho tôi biết tôi đang làm gì sai!

Trả lời

12

Nếu chúng ta sẵn sàng hy sinh tính cô đọng dung dịch Hayden, người ta cũng có thể làm một cái gì đó như thế này:

In [22]: orders_df['C'] = orders_df.Action.apply(
       lambda x: (1 if x == 'Sell' else -1)) 

In [23]: orders_df # New column C represents the sign of the transaction 
Out[23]: 
    Prices Amount Action C 
0  3  57 Sell 1 
1  89  42 Sell 1 
2  45  70 Buy -1 
3  6  43 Sell 1 
4  60  47 Sell 1 
5  19  16 Buy -1 
6  56  89 Sell 1 
7  3  28 Buy -1 
8  56  69 Sell 1 
9  90  49 Buy -1 

Bây giờ chúng tôi đã loại bỏ sự cần thiết của báo cáo kết quả if. Sử dụng DataFrame.apply(), chúng tôi cũng xóa bỏ vòng lặp for. Như Hayden lưu ý, các hoạt động được vector hóa luôn nhanh hơn.

In [24]: orders_df['Value'] = orders_df.Prices * orders_df.Amount * orders_df.C 

In [25]: orders_df # The resulting dataframe 
Out[25]: 
    Prices Amount Action C Value 
0  3  57 Sell 1 171 
1  89  42 Sell 1 3738 
2  45  70 Buy -1 -3150 
3  6  43 Sell 1 258 
4  60  47 Sell 1 2820 
5  19  16 Buy -1 -304 
6  56  89 Sell 1 4984 
7  3  28 Buy -1 -84 
8  56  69 Sell 1 3864 
9  90  49 Buy -1 -4410 

Giải pháp này cần hai dòng mã thay vì một, nhưng dễ đọc hơn một chút. Tôi nghi ngờ rằng chi phí tính toán cũng tương tự.

17

Bạn có thể sử dụng phương pháp DataFrame apply:

order_df['Value'] = order_df.apply(lambda row: (row['Prices']*row['Amount'] 
               if row['Action']=='Sell' 
               else -row['Prices']*row['Amount']), 
            axis=1) 

Nó thường nhanh hơn để sử dụng các phương pháp chứ không phải qua vòng lặp for.

+0

rực rỡ, cảm ơn rất nhiều !! – OAK

58

Tôi nghĩ rằng một giải pháp thanh lịch là sử dụng phương pháp where (cũng thấy API docs):

In [37]: values = df.Prices * df.Amount 

In [38]: df['Values'] = values.where(df.Action == 'Sell', other=-values) 

In [39]: df 
Out[39]: 
    Prices Amount Action Values 
0  3  57 Sell  171 
1  89  42 Sell 3738 
2  45  70 Buy -3150 
3  6  43 Sell  258 
4  60  47 Sell 2820 
5  19  16 Buy -304 
6  56  89 Sell 4984 
7  3  28 Buy  -84 
8  56  69 Sell 3864 
9  90  49 Buy -4410 

Hơn nữa đây sẽ là giải pháp nhanh nhất.

+0

cảm ơn vì giải pháp, cả hai đều hoạt động rất tốt. – OAK

+3

bạn có thể chỉ ra rằng điều này trả lời câu hỏi của bạn? –

+1

Đánh dấu câu trả lời này là câu trả lời của bạn, @OAK – Blairg23

0

Đối với tôi, đây là rõ ràng và trực quan nhất:

values = [] 
for action in ['Sell','Buy']: 
    amounts = orders_df['Amounts'][orders_df['Action'==action]].values 
    if action == 'Sell': 
     prices = orders_df['Prices'][orders_df['Action'==action]].values 
    else: 
     prices = -1*orders_df['Prices'][orders_df['Action'==action]].values 
    values += list(amounts*prices) 
orders_df['Values'] = values 

Phương pháp .values trả về một numpy array phép bạn dễ dàng nhân tố khôn ngoan và sau đó bạn tích lũy có thể tạo ra một danh sách bằng 'thêm' với nó .

3

Vì câu hỏi này xuất hiện trở lại, tôi nghĩ cách tiếp cận rõ ràng là sử dụng assign.

Mã này là khá diễn cảm và tự mô tả:

df = df.assign(Value = lambda x: x.Prices * x.Amount * x.Action.replace({'Buy' : 1, 'Sell' : -1})) 
Các vấn đề liên quan