2015-04-02 56 views
2

我想合併列Name和Depth上的兩個數據幀。左df中的深度具有單個深度列(「深度」)。然而,右邊的df有兩個深度列('top_depth'和'bottom_depth')。在Pandas中,合併兩個具有複雜多索引的dataframs

我想從左邊的df中取出每條記錄,如果可用的話,如果'深度'落在'top_depth'和'bottom_depth'之間,則從右邊的df分配一條記錄。

我已經把一些簡單的dataframes:

df1 = pd.DataFrame(np.array([ 
    ['b1', 4, 9], 
    ['b1', 5, 61], 
    ['b1', 15, 95], 
    ['b1', 24, 9], 
    ['b2', 4, 5], 
    ['b2', 6, 6], 
    ['b2', 44, 0]]), 
    columns=['name', 'depth', 'attr1']) 
df2 = pd.DataFrame(np.array([ 
    ['b1', 1, 6, 66], 
    ['b1', 14, 16, 99], 
    ['b1', 51, 55, 9], 
    ['b3', 0, 5, 32]]), 
    columns=['name', 'top_depth', 'bottom_depth', 'attr2']) 

然後合併得到這個:

>>> df3 
    name depth top_depth bottom_depth attr1 attr2 
0 b1 4.0  1.0   6.0 9.0 66.0 
1 b1 5.0  1.0   6.0 61.0 66.0 
2 b1 15.0  14.0   16.0 95.0 99.0 
3 b1 24  NaN   NaN  9 NaN 
4 b2  4  NaN   NaN  5 NaN 
5 b2  6  NaN   NaN  6 NaN 
6 b2 44  NaN   NaN  0 NaN 

我相信我能想出一個強力的方法來此,但有有要成爲一個更好,更多熊貓的方式。

+0

第3行(df2)中的b3發生了什麼? – 2015-04-02 23:11:26

+1

爲什麼df2 ['top_depth'] - df2 ['bottom_depth']不一致正面或負面? – 2015-04-02 23:15:46

+0

利亞姆你發現我的錯誤。 df2(第2行)中的第三行應該是51,55而不是55,51。我編輯了我的問題。謝謝。 df2 ['bottom_depth'] - df2 ['top_depth']應始終爲正值。 – Todd 2015-04-03 00:00:11

回答

0

您可以join(在指數):

In [11]: df1.join(df2, how='outer', rsuffix='_') 
Out[11]: 
    name depth attr1 name_ top_depth bottom_depth attr2 
0 b1  4  9 b1   1   6 66 
1 b1  5 61 b1  14   16 99 
2 b1 15 95 b1  55   51  9 
3 b1 24  9 b3   0   5 32 
4 b2  4  5 NaN  NaN   NaN NaN 
5 b2  6  6 NaN  NaN   NaN NaN 
6 b2 44  0 NaN  NaN   NaN NaN 

注:起名字列不匹配rsuffix要求......目前尚不清楚你想用這種情況下該怎麼做。


注:np.array強制陣列共享(?初始)數據類型,在這種情況下,這意味着所有的數字都是字符串。您可以傳遞一個普通的Python列表到DataFrame!

這裏的一個略微低效的方法,首先必須功能,其中查找名稱,並檢查該深度是頂部和底部內:

def get_depth_group(name, depth): 
    arr = (df2.name == name) & (df2.bottom_depth > depth) & (depth > df2.top_depth) 
    return df2.iloc[arr.argmax()] if any(arr) else np.nan 

這可能是更有效地使用不同的數據結構爲這...但這會工作!

In [21]: df1[['depth', 'attr1']].join(df1.apply(lambda x: get_depth_group(x['name'], x['depth']), axis=1)) 
Out[21]: 
    depth attr1 name top_depth bottom_depth attr2 
0  4  9 b1   1    6  66 
1  5  61 b1   1    6  66 
2  15  95 b1   14   16  99 
3  24  9 NaN  NaN   NaN NaN 
4  4  5 NaN  NaN   NaN NaN 
5  6  6 NaN  NaN   NaN NaN 
6  44  0 NaN  NaN   NaN NaN 
+0

這很好用!謝謝您的幫助。 – Todd 2015-04-03 02:39:31

0

部分:

import pandas as pd 
import numpy as np 

df1 = pd.DataFrame(np.array([ 
    ['b1', 4, 9], 
    ['b1', 5, 61], 
    ['b1', 15, 95], 
    ['b1', 24, 9], 
    ['b2', 4, 5], 
    ['b2', 6, 6], 
    ['b2', 44, 0]]), 
    columns=['name', 'depth', 'attr1']) 
df2 = pd.DataFrame(np.array([ 
    ['b1', 1, 6, 66], 
    ['b1', 14, 16, 99], 
    ['b1', 51, 55, 9], 
    ['b3', 0, 5, 32]]), 
    columns=['name', 'top_depth', 'bottom_depth', 'attr2']) 

om = pd.ordered_merge(df2, df1) 
om = om.convert_objects(convert_numeric=True) 
sandwiched = om.query('(depth > top_depth) & (depth <= bottom_depth)') 

夾是:

name top_depth bottom_depth attr2 depth attr1 
0 b1   1    6  66  4  9 
1 b1   1    6  66  5  61 
6 b1   14   16  99  15  95 

我想你可以使用join我不記得附上DF1的其餘部分。

它畢竟可能不是一個SQL形問題 - 你能否認爲它們是按深度和top_depth排序的?和df2範圍重疊?遍歷每個數據幀一次可能是有效的方式。