2014-02-25 300 views
0

鑑於數據幀df一個數據幀:更新基於另一個數據框

Id Sex Group Time Time! 
0 21 M  2 2.31 NaN 
1 2 F  2 2.29 NaN 

update

Id Sex Group Time 
0 21 M  2 2.36 
1 2 F  2 2.09 
2 3 F  1 1.79 

我想匹配IdSexGroup,要麼更新Time!Time值(從df)如果匹配,或者插入新記錄。

這是我如何做到這一點:

df = df.set_index(['Id', 'Sex', 'Group']) 
update = update.set_index(['Id', 'Sex', 'Group']) 

for i, row in update.iterrows(): 
    if i in df.index: # update 
     df.ix[i, 'Time!'] = row['Time'] 
    else:    # insert new record 
     cols = up.columns.values 
     row = np.array(row).reshape(1, len(row)) 
     _ = pd.DataFrame(row, index=[i], columns=cols) 
     df = df.append(_) 

print df 

       Time Time! 
Id Sex Group    
21 M 2  2.31 2.36 
2 F 2  2.29 2.09 
3 F 1  1.79 NaN 

的代碼似乎工作,我想結果與上述一致。不過,我已經注意到了這個faultily表現上了一個大的數據集,與條件

if i in df.index: 
    ... 
else: 
    ... 

工作顯然是錯誤的(它會繼續else和副詩句,它應該不會,我想,這多指標可能不知何故)。

所以我的問題是,你知道任何其他方式,或更強大的版本,我更新一個DF基於另一個DF?

+0

我認爲您的預期存在一個錯誤,2.09行在更新中沒有組= 1。 –

+0

我認爲你的預期產出有一個錯字順便說一句。在你提供的例子中沒有'(2,F,1)' – TomAugspurger

+0

確定Andy,首先你擊敗我的回答,現在我的評論:) – TomAugspurger

回答

3

我想我會用合併來做到這一點,然後用where來更新列。首先刪除時間列:

In [11]: times = up.pop('Time') # up = the update DataFrame 

In [12]: df1 = df.merge(up, how='outer') 

In [13]: df1 
Out[13]: 
    Id Sex Group Time Time! 
0 21 M  2 2.31 NaN 
1 2 F  2 2.29 NaN 
2 3 F  1 NaN NaN 

更新時間,如果它不是NaN和時間!如果是NaN:

In [14]: df1['Time!'] = df1['Time'].where(df1['Time'].isnull(), times) 

In [15]: df1['Time'] = df1['Time'].where(df1['Time'].notnull(), times) 

In [16]: df1 
Out[16]: 
    Id Sex Group Time Time! 
0 21 M  2 2.31 2.36 
1 2 F  2 2.29 2.09 
2 3 F  1 1.79 NaN