2016-11-24 13 views
3

私は3つのデータフレーム:df1,df2df3を持っています。私はの値を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の間の数字。したがって、番号5df1に配置されています。 (このケースでは、私は唯一の2行を持っていますが、彼らはより多くをすることができる)df3の残りの行のために、このような動作を繰り返し、最終的な結果は次のようにする必要があります:

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

私は数行であなたのループよりも、同じ結果を達成するため、2つの同様のオプションを提供することができます

が適用1.Usingとfillna()fillnaが2倍combine_firstよりも高速です):

を機能を2.Using
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() 

(あなたは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) 

またはわずかなバリアリグローバル定義に頼らない:あなたのソリューションは、さえもはるかに冗長なのに、(私の両方のために9.5ミリ秒対7.5ミリ秒)この小さなデータセットを最小の時間がかかります

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) 

注意。どちらの場合も、行のループの問題は、df3

の行の問題であるため、速度は似ています
関連する問題