2016-12-02 92 views
0

我有兩個熊貓數據框,我想與規則結合使用。如何將兩個熊貓數據框與條件結合?

這是第一個數據幀

import pandas as pd 
df1 = pd.Dataframe() 

df1 

rank begin end  labels 
first 30953 31131 label1 
first 31293 31435 label2 
first 31436 31733 label4 
first 31734 31754 label1 
first 32841 33037 label3 
second 33048 33456 label4 
.... 

第二數據幀是僅兩列,rankstart

df2 

rank start 
first 31333  
first 31434  
first 33039  
first 33123  
first 33125  

在第一數據幀df1,所述數據具有beginend。我想檢查df2中的開始整數是否在這個範圍內。

下面是最終的結果應該是這樣的:

result 

rank start  labels 
first 31333  label2 
first 31434  label2 
first 33039  NaN 
first 33123  label4 
first 33125  label4 

start==31333df1label = label231435範圍31293之間。整數31434也在範圍31293:31435之間,所以它也被註釋爲label2。值33039不在df2之間的任何區間之間,因此它獲得NaN值。

由這些dataframes被組合的規則是這樣的:

(df2.start >= df1.begin) & (df2.start <= df1.end) 

但同時,每行必須在相同的秩值,例如匹配每行必須匹配此條件的第一個或第二個字符串。

下面是我用這兩個dataframes結合的代碼,但它不會在所有規模非常好:

from numpy import nan 

def between_range(row): 
    subset = df1.loc[(row["rank"] == df1.rank) & (row.start >= repeats.start) & (row.start <= repeats.end), :] 
    if subset.empty: 
     return np.nan 
    return subset.labels 

有另一種方式與合併(也許秩)來做到這一點?任何其他基於熊貓的解決方案?

+0

@Kartik我試圖簡化這裏的問題。感謝您的幫助 – EB2127

+0

@MaxU我已經更新了上述內容。任何想法如何擴展/工作? – EB2127

回答

1

試試這個代碼塊

def match_labels(row): 
    curr_df = df1[ (df1['rank']==row['rank']) & (df1['begin']<=row['start']) & (df1['end']>=row['start']) ] 
    try: 
     row['labels'] = curr_df['labels'].iloc[0] 
    except: 
     row['labels'] = np.NaN 

    return row 

result = df2.apply(lambda x:match_labels(x),axis=1) 

希望這有助於

+0

感謝您的迴應。爲什麼當我的腳本運行幾天而沒有任何顯示時,這將工作? – EB2127

1

你可以用大量快速千方百計加入,如果你能適應len(df1)*len(df2)行數據到內存:

df = df2.merge(df1, how = 'left') 
df = df.loc[(df.start >= df.begin) & (df.start <= df.end),['rank','start','labels']] # This gives you the correct label of every entry that does indeed belong to a label. 
result = df2.merge(df, how = 'left') # This effectively adds the entries that do not belong to any label back into df. 

這當start落在多於一個的範圍內和end對:在這種情況下,您將獲得與匹配標籤相同數量的行。

如果您不能裝入內存,您可以嘗試通過rank分區數據:只是那些rank == 'first',然後rank == 'second'做到這一點,等等。例如begin,endstartdf = df2[(df2.start > 31000) & (df2.start <= 32000)].merge(df1[(df1.begin > 31000) & (df1.end <= 32000)], how = 'left')

+0

「如果你不能把它放到內存中,你可以嘗試按rank排列數據:只對rank =='first',然後rank =='second',等等。你可以說得更詳細點嗎?你會嘗試 'df_rank1 = df.loc [(df.start> = df.begin)&(df.start <= df.end)&(rank =='first',['rank','start', '標籤']]' 'result_rank1 = df2.merge(df,how ='left')' 然後將所有這些連接在一起? – EB2127

+0

我已經編輯了我的答案。看看代碼是如何工作的,試着用更小的數據子集來運行它,看看每行代碼是什麼。 –

+0

當使用較小的子集時,例如'rank =='first''等,所需的RAM太大。但是,如果我要實現這一點,我怎麼可以使用'for'循環爲每個「dataframe子部分」執行這些命令,然後將它們放在一起? – EB2127