2016-09-02 18 views
5

Tôi đang thực hiện một thao tác phức tạp hơn trên một khung dữ liệu mà tôi so sánh hai hàng có thể ở bất kỳ vị trí nào trong khung.Pandas: Nhận giá trị duy nhất của một chuỗi hoặc nan nếu nó không tồn tại

Dưới đây là một ví dụ:

import pandas as pd 
import numpy as np 

D = {'A':['a','a','c','e','e','b','b'],'B':['c','f','a','b','d','a','e']\ 
,'AW':[1,2,3,4,5,6,7],'BW':[10,20,30,40,50,60,70]} 
P = pd.DataFrame(D) 
P = P.sort_values(['A','B']) 
P['AB'] = P.A+'_'+P.B 
P['AWBW'] = P.AW+P.BW 

Bây giờ những gì tôi đang làm gì ở đây là tôi có cặp của chuỗi trong AB, ví dụ a_c mà tôi gọi AB. Và tôi cũng có ghép nối ngược c_a. Tôi tính tổng số các số AWBW cho mỗi cặp, được gọi là AWBW.

Bây giờ tôi muốn trừ giá trị tổng của a_c từ giá trị c_a và thực hiện tương tự cho mọi cặp chuỗi trong đó cả hai biến thể tồn tại. Tất cả các giá trị khác chỉ nên NaN, vì vậy kết quả của tôi sẽ giống như thế này:

A AW B BW AB AWBW RowDelta 
0 a 1 c 10 a_c 11  -22.0 
1 a 2 f 20 a_f 22  NaN 
5 b 6 a 60 b_a 66  NaN 
6 b 7 e 70 b_e 77  33.0 
2 c 3 a 30 c_a 33  22.0 
3 e 4 b 40 e_b 44  -33.0 
4 e 5 d 50 e_d 55  NaN 

Tôi đã gần như giải quyết được cách để làm điều này, nhưng có một vấn đề trái tôi bị mắc kẹt tại.

Đây là giải pháp của tôi cho đến nay:

for i,row in P.iterrows(): 
    P.ix[i,'RowDelta'] = row['AWBW']\ 
    - P[(P['A'] == row.AB[2]) & (P['B'] == row.AB[0])]['AWBW'].get(0,np.nan) 

Vấn đề là P[(P['A'] == row.AB[2]) & (P['B'] == row.AB[0])]['AWBW'] trả về một loạt mà hoặc là rỗng hoặc có đúng một phần tử có chỉ số tuy nhiên có thể thay đổi.

Bây giờ phương thức series.get giải quyết vấn đề trả về NaN khi chuỗi trống nhưng muốn giá trị chỉ số dứt khoát, trong trường hợp này tôi sử dụng 0, nhưng tôi không thể có chỉ mục động tại đó.

Tôi không thể làm điều này cho ví dụ

T = P[(P['A'] == row.AB[2]) & (P['B'] == row.AB[0])]['AWBW'] 
T.get(T.index[0],np.nan) 

vì không có chỉ số nếu series là trống rỗng và điều này dẫn đến một lỗi khi làm T.index[0]. Cũng vậy với những nỗ lực của tôi bằng cách sử dụng iloc.

Có cách nào để tự động nhận chỉ mục không xác định của một chuỗi nếu có một phần tử (và không bao giờ nhiều hơn một) trong khi xử lý trường hợp của một chuỗi rỗng không?

+1

bắt đầu bằng cách hợp nhất một phần tách '' AB'' trên chính đảo ngược của nó. 'AB = P.AB.str.split ('_', expand = True)' theo sau bởi 'AB.merge (AB, left_on = [0, 1], right_on = [1, 0])'. – piRSquared

+0

Tôi đã làm cho nó hoạt động, cảm ơn. Tôi sẽ trả lời câu hỏi của riêng tôi với điều này sau đó. – Khris

Trả lời

2

tín dụng đi vào piRSquared đã chỉ cho tôi vào đúng hướng cho các giải pháp:

AB = P.AB.str.split('_', expand=True) 
AB = AB.merge(AB, left_on=[0, 1], right_on=[1, 0],how='inner')[[0,1]] 
AB = AB.merge(P,left_on=[0,1], right_on=['A','B'])[['A','AW','B','BW']] 
AB = AB.merge(P,left_on=['A','B'], right_on=['B','A'])[['AW_x','BW_x','AW_y','BW_y','AB']] 
AB['RowDelta'] = AB.AW_y+AB.BW_y-AB.AW_x-AB.BW_x 
P = P.merge(AB[['AB','RowDelta']],on='AB',how='outer') 

Có lẽ nó có thể được thực hiện ngắn hơn hoặc đẹp hơn, nó hoạt động cho chắc chắn.

Các vấn đề liên quan