2014-07-14 43 views
6

Tôi có hai khung dữ liệu Pandas, một khối khá lớn (30000+ hàng) và một hàng nhỏ hơn (100+ hàng).Các hàng phù hợp trong một khung dữ liệu Pandas đến một cột khác dựa trên ba cột

DFA trông giống như sau:

 X  Y ONSET_TIME COLOUR 
0 104 78   1083   6  
1 172 78   1083  16 
2 240 78   1083  15 
3 308 78   1083   8 
4 376 78   1083   8 
5 444 78   1083  14 
6 512 78   1083  14 
... ... ...   ...  ... 

DFB trông giống như sau:

TIME  X  Y 
0  7 512 350 
1 1722 512 214 
2 1906 376 214 
3 2095 376 146 
4 2234 308 78 
5 2406 172 146 
... ... ... ... 

Những gì tôi muốn làm là cho mỗi dòng trong DFB để tìm hàng trong DFA nơi các giá trị của các cột X VÀ Y bằng nhau VÀ đó là hàng đầu tiên mà giá trị của dfB ['TIME'] lớn hơn dfA ['ONSET_TIME'] và trả về giá trị của dfA ['COLOR'] cho hàng này.

dfA đại diện cho làm mới màn hình, trong đó X và Y là tọa độ của các mục trên màn hình và do đó lặp lại cho mỗi ONSET_TIME khác nhau (có 108 cặp tọa độ cho mỗi giá trị ONSET_TIME).

Sẽ có nhiều hàng trong đó X và Y trong hai khung dữ liệu bằng nhau, nhưng tôi cũng cần có một hàng phù hợp với thời gian.

Tôi đã làm điều này bằng cách sử dụng cho vòng lặp và nếu câu lệnh chỉ để thấy rằng nó có thể được thực hiện, nhưng rõ ràng cho kích thước của các khung dữ liệu này phải mất một thời gian rất dài.

for s in range(0, len(dfA)): 
    for r in range(0, len(dfB)): 
     if (dfB.iloc[r,1] == dfA.iloc[s,0]) and (dfB.iloc[r,2] == dfA.iloc[s,1]) and (dfA.iloc[s,2] <= dfB.iloc[r,0] < dfA.iloc[s+108,2]): 
      return dfA.iloc[s,3] 

Trả lời

5

Có lẽ là một cách hiệu quả hơn để làm điều này, nhưng đây là một phương pháp không những chậm cho vòng:

import pandas as pd 

dfB = pd.DataFrame({'X':[1,2,3],'Y':[1,2,3], 'Time':[10,20,30]}) 
dfA = pd.DataFrame({'X':[1,1,2,2,2,3],'Y':[1,1,2,2,2,3], 'ONSET_TIME':[5,7,9,16,22,28],'COLOR': ['Red','Blue','Blue','red','Green','Orange']}) 

#create one single table 
mergeDf = pd.merge(dfA, dfB, left_on = ['X','Y'], right_on = ['X','Y']) 
#remove rows where time is less than onset time 
filteredDf = mergeDf[mergeDf['ONSET_TIME'] < mergeDf['Time']] 
#take min time (closest to onset time) 
groupedDf = filteredDf.groupby(['X','Y']).max() 

print filteredDf 

COLOR ONSET_TIME X Y Time 
0  Red   5 1 1 10 
1 Blue   7 1 1 10 
2 Blue   9 2 2 20 
3  red   16 2 2 20 
5 Orange   28 3 3 30 


print groupedDf 

COLOR ONSET_TIME Time 
X Y       
1 1  Red   7 10 
2 2  red   16 20 
3 3 Orange   28 30 

Ý tưởng cơ bản là hợp nhất hai bảng để bạn có thời gian cùng nhau trong một bảng. Sau đó, tôi lọc trên recs là lớn nhất (gần nhất với thời gian trên dfB của bạn). Hãy cho tôi biết nếu bạn có câu hỏi về điều này.

+0

Đó là cảm ơn thực sự hữu ích, mặc dù tôi thấy rằng groupedDf cuối cùng của bạn đã thiếu một số giá trị từ DfB gốc. Tôi đã thử: filterDF.sort ('ONSET_TIME'). Groupby (['DfB_INDEX'], as_index = False) .max() Và điều đó mang lại cho tôi giá trị mà tôi đang tìm kiếm theo như tôi có thể nói. –

0

Sử dụng merge() - hoạt động như JOIN trong SQL - và bạn đã hoàn thành phần đầu tiên.

d1 = '''  X  Y ONSET_TIME COLOUR 
    104 78   1083   6  
    172 78   1083  16 
    240 78   1083  15 
    308 78   1083   8 
    376 78   1083   8 
    444 78   1083  14 
    512 78   1083  14 
    308 78   3000  14 
    308 78   2000  14''' 


d2 = ''' TIME  X  Y 
     7 512 350 
    1722 512 214 
    1906 376 214 
    2095 376 146 
    2234 308 78 
    2406 172 146''' 

import pandas as pd 
from StringIO import StringIO 

dfA = pd.DataFrame.from_csv(StringIO(d1), sep='\s+', index_col=None) 
#print dfA 

dfB = pd.DataFrame.from_csv(StringIO(d2), sep='\s+', index_col=None) 
#print dfB 

df1 = pd.merge(dfA, dfB, on=['X','Y']) 
print df1 

kết quả:

 X Y ONSET_TIME COLOUR TIME 
0 308 78  1083  8 2234 
1 308 78  3000  14 2234 
2 308 78  2000  14 2234 

Sau đó, bạn có thể sử dụng nó để lọc kết quả.

df2 = df1[ df1['ONSET_TIME'] < df1['TIME'] ] 
print df2 

kết quả:

 X Y ONSET_TIME COLOUR TIME 
0 308 78  1083  8 2234 
2 308 78  2000  14 2234 
+0

anh ấy cũng muốn có thời gian lớn hơn onset_time. Thêm df = pd.merge (dfA, dfB, on = ['X', 'Y']); df = df [df ["ONSET_TIME"]> df ["TIME"]] – ZJS

+0

Cảm ơn, tôi đã thực hiện nó trong khi đó :) Tôi làm nó từng mảnh - kiểm tra nó - và thêm vào câu trả lời. Bằng cách này tôi tìm hiểu 'pandas' :) – furas

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