2016-11-24 191 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

相关问题