2016-11-24 186 views
3

我有3個數據幀:df1,df2,df3。我正在填寫NaN的值df1,其中包含df2中的一些值。從df2中選擇的值也根據處理df3中存儲的一些數據的簡單功能(mul_val)的輸出進行選擇。用Pandas替換另一個數據幀中的數據幀中的值

我能夠得到這樣的結果,但我想找到一個更簡單,更簡單的方法和更可讀的代碼。

這是我到目前爲止有:

import pandas as pd 
import numpy as np 

# simple function 
def mul_val(a,b): 
    return a*b 

# dataframe 1 
data = {'Name':['PINO','PALO','TNCO' ,'TNTO','CUCO' ,'FIGO','ONGF','LABO'], 
     'Id' :[ 10 , 9 ,np.nan , 14 , 3 ,np.nan, 7 ,np.nan]} 
df1 = pd.DataFrame(data) 

# dataframe 2 
infos = {'Info_a':[10,20,30,40,70,80,90,50,60,80,40,50,20,30,15,11], 
     'Info_b':[10,30,30,60,10,85,99,50,70,20,30,50,20,40,16,17]} 
df2 = pd.DataFrame(infos) 

dic = {'Name': {0: 'FIGO', 1: 'TNCO'}, 
     'index': {0: [5, 6], 1: [11, 12, 13]}} 
df3 = pd.DataFrame(dic) 

#---------------Modify from here in the most efficient way!----------------- 

for idx,row in df3.iterrows(): 
    store_val = [] 
    print(row['Name']) 
    for j in row['index']: 
     store_val.append([mul_val(df2['Info_a'][j],df2['Info_b'][j]),j]) 
    store_val = np.asarray(store_val) 

    # - Identify which is the index of minimum value of the first column 
    indx_min_val = np.argmin(store_val[:,0]) 

    # - Get the value relative number contained in the second column 
    col_value = row['index'][indx_min_val] 

    # Identify value to be replaced in df1 
    value_to_be_replaced = df1['Id'][df1['Name']==row['Name']] 

    # - Replace such value into the df1 having the same row['Name'] 
    df1['Id'].replace(to_replace=value_to_be_replaced,value=col_value, inplace=True) 

通過在每次迭代印刷store_val我得到:

FIGO 
[[6800 5] 
[8910 6]] 
TNCO 
[[2500 11] 
[ 400 12] 
[1200 13]] 

讓我們做一個簡單的例子:考慮FIGO,我確定6800作爲最低數字在68008910之間。因此,我選擇放置在df1中的號碼5。重複這樣的操作的df3其餘行(在這種情況下,我只有2行,但他們可能是多了很多),最後的結果應該是這樣的:

In[0]: before   In[0]: after 
Out[0]:     Out[0]: 
    Id Name    Id Name 
0 10.0 PINO   0 10.0 PINO 
1 9.0 PALO   1 9.0 PALO 
2 NaN TNCO -----> 2 12.0 TNCO 
3 14.0 TNTO   3 14.0 TNTO 
4 3.0 CUCO   4 3.0 CUCO 
5 NaN FIGO -----> 5 5.0 FIGO 
6 7.0 ONGF   6 7.0 ONGF 
7 NaN LABO   7 NaN LABO 

諾爾:您還可以刪除的如果需要循環,並使用不同類型的格式來存儲數據(列表,數組...);重要的是最終的結果仍然是一個數據框。

回答

1

我可以提供的是實現比你在幾行循環的結果相同兩個類似的選項:

1.使用申請和fillna()fillna是兩個因素比combine_first更快):

df3['Id'] = df3.apply(lambda row: (df2.Info_a*df2.Info_b).loc[row['index']].argmin(), axis=1) 
    df1 = df1.set_index('Name').fillna(df3.set_index('Name')).reset_index() 

2.使用功能(拉姆達不支持任務,所以你必須申請一個FUNC)

def f(row): 
    df1.ix[df1.Name==row['Name'], 'Id'] = (df2.Info_a*df2.Info_b).loc[row['index']].argmin() 
df3.apply(f, axis=1) 

或輕微瓦里螞蟻不依賴全局定義:

def f(row, df1, df2): 
    df1.ix[df1.Name==row['Name'], 'Id'] = (df2.Info_a*df2.Info_b).loc[row['index']].argmin() 
df3.apply(f, args=(df1,df2,), axis=1) 

請注意,您的解決方案,儘管更詳細的,需要的時間最少有這個小數據集(7.5毫秒與9.5 ms所有礦井)。速度是相似的,因爲在這兩種情況下,它都是循環的行數df3

相關問題