2016-03-22 8 views
1

私は以下の形式でデータフレーム持っている:私は最初のオプションは最大プット最大尺度であるならば、Aの場合Pythonで行の組み合わせとして列を取得するには?

としてロジックと出力の下にDFの上に変換しようとしています

country region max min 
A   R1 141 86 
A   R2 215 72 
A   R3 473 36 
B   R1 384 79 
B   R2 439 88 
B   R3 172 54 

を、 分すべてを休まA以外の場合は、2番目のオプションが最大であれば、最大測定値を入れ、すべて安静にしてください

注:追加のデフォルトオプション(分)があります。

country region measure Option1 Option2 
A R1 86 min min 
A R2 72 min min 
A R3 36 min min 
A R1 86 min max 
A R2 72 min max 
A R3 36 min max 
A R1 86 min default 
A R2 72 min default 
A R3 36 min default 
A R1 86 default min 
A R2 72 default min 
A R3 36 default min 
A R1 86 default default 
A R2 72 default default 
A R3 36 default default 
A R1 86 default max 
A R2 72 default max 
A R3 36 default max 
A R1 141 max min 
A R2 215 max min 
A R3 473 max min 
A R1 141 max default 
A R2 215 max default 
A R3 473 max default 
A R1 141 max max 
A R2 215 max max 
A R3 473 max max 
B R1 79 min min 
B R2 88 min min 
B R3 54 min min 
B R1 384 min max 
B R2 439 min max 
B R3 172 min max 
B R1 79 min default 
B R2 88 min default 
B R3 54 min default 
B R1 79 default min 
B R2 88 default min 
B R3 54 default min 
B R1 79 default default 
B R2 88 default default 
B R3 54 default default 
B R1 384 default max 
B R2 439 default max 
B R3 172 default max 
B R1 79 max min 
B R2 88 max min 
B R3 54 max min 
B R1 79 max default 
B R2 88 max default 
B R3 54 max default 
B R1 384 max max 
B R2 439 max max 
B R3 172 max max 

私はいくつかのトリックで融解オプションがここで動作することができますが、初心者であることを正しく理解できないことを理解しています。

コードの下に使用して達成

EDIT1を助けてください

誰かが微調整にそれを手伝ってくれるし、パフォーマンスを向上させることができますか?

d1 = pd.melt(data, id_vars=['country','region'], value_vars=['max', 'min','default']).sort(['country','region']).reset_index(drop=True) 

for ridx,i in enumerate(d1['value']): 
    if pd.isnull(i): 
     d1['value'].loc[ridx] = d1['value'].loc[ridx-1] 
    else: 
     pass 

d2 = d1 

from pandas import DataFrame, merge 
d1['key'] = 1 
d2['key'] = 1 
d3 = merge(d1, d2, on='key') 

d3 = d3.drop(['key'],axis=1) 

for index, row in d3.iterrows(): 
    if d3['region_x'].loc[index] == d3['region_y'].loc[index] and d3['country_x'].loc[index] == d3['country_y'].loc[index]: 
     pass 
    else: 
     d3 = d3.drop([index]) 
d3 = d3.reset_index(drop=True) 

d3['rate'] = "" 


for index, row in d3.iterrows(): 
    if d3['country_x'].loc[index] == 'A': 
     d3['rate'].loc[index] = d3['value_x'].loc[index] 
    else: 
     d3['rate'].loc[index] = d3['value_y'].loc[index] 

d3 = d3.drop(['value_x','country_y','region_y','value_y'],axis=1) 

d3.columns = ['country','region','Option1','Option2','measure'] 
d3 = d3[['country','region','measure','Option1','Option2']] 

よろしく、

答えて

1

あなたがnumpy.in1dastypefillnanumpy.whereを使用することができます。

d1 = pd.melt(data, id_vars=['country','region'], value_vars=['max', 'min','default']) 
     .sort_values(['country','region']).reset_index(drop=True) 

#fill NaN in column value method ffill 
#(propagate last valid observation forward to next valid) 
d1['value'] = d1['value'].fillna(method='ffill') 

d1['key'] = 1 
#you can use double d1 
d3 = pd.merge(d1, d1, on='key') 
d3 = d3.drop(['key'],axis=1) 

#filter columns by conditions - boolean indexing 
d3 = d3[(d3['region_x'] == d3['region_y']) & (d3['country_x'] == d3['country_y'])] 
     .reset_index(drop=True) 

#if condition is true get value_x else value_y 
#if neccesarry, convert to int by astype(int) 
d3['rate'] = np.where(np.in1d(d3['country_x'], 'A'), d3['value_x'],d3['value_y']).astype(int) 

d3 = d3.drop(['value_x','country_y','region_y','value_y'],axis=1) 

d3.columns = ['country','region','Option1','Option2','measure'] 
d3 = d3[['country','region','measure','Option1','Option2']] 

タイミング

新しいソリューションは、主に無ループので、300倍高速でありますiterrows()

In [67]: %timeit old(data) 
1 loops, best of 3: 2.46 s per loop 

In [68]: %timeit new(data1) 
100 loops, best of 3: 8.33 ms per loop 

コード

data1 = data.copy() 

def old(data): 
    d1 = pd.melt(data, id_vars=['country','region'], value_vars=['max', 'min','default']).sort_values(['country','region']).reset_index(drop=True) 

    for ridx,i in enumerate(d1['value']): 
     if pd.isnull(i): 
      d1['value'].loc[ridx] = d1['value'].loc[ridx-1] 
     else: 
      pass 
    d2 = d1 
    d1['key'] = 1 
    d2['key'] = 1 
    d3 = pd.merge(d1, d2, on='key') 

    d3 = d3.drop(['key'],axis=1) 

    for index, row in d3.iterrows(): 
     if d3['region_x'].loc[index] == d3['region_y'].loc[index] and d3['country_x'].loc[index] == d3['country_y'].loc[index]: 
      pass 
     else: 
      d3 = d3.drop([index]) 
    d3 = d3.reset_index(drop=True) 

    d3['rate'] = "" 

    for index, row in d3.iterrows(): 
     if d3['country_x'].loc[index] == 'A': 
      d3['rate'].loc[index] = d3['value_x'].loc[index] 
     else: 
      d3['rate'].loc[index] = d3['value_y'].loc[index] 

    d3 = d3.drop(['value_x','country_y','region_y','value_y'],axis=1) 

    d3.columns = ['country','region','Option1','Option2','measure'] 
    d3 = d3[['country','region','measure','Option1','Option2']] 
    return d3  
def new(data): 
    d1 = pd.melt(data, id_vars=['country','region'], value_vars=['max', 'min','default']).sort_values(['country','region']).reset_index(drop=True) 

    #fill NaN in column value method ffill (propagate last valid observation forward to next valid) 
    d1['value'] = d1['value'].fillna(method='ffill') 

    d1['key'] = 1 
    #you can use double d1 
    d3 = pd.merge(d1, d1, on='key') 
    d3 = d3.drop(['key'],axis=1) 

    #filter columns by conditions - boolean indexing 
    d3 = d3[(d3['region_x'] == d3['region_y']) & (d3['country_x'] == d3['country_y'])].reset_index(drop=True) 

    #if condition is true get value_x else value_y 
    #if neccesarry, convert to int by astype(int) 
    d3['rate'] = np.where(np.in1d(d3['country_x'], 'A'), d3['value_x'],d3['value_y']).astype(int) 

    d3 = d3.drop(['value_x','country_y','region_y','value_y'],axis=1) 

    d3.columns = ['country','region','Option1','Option2','measure'] 
    d3 = d3[['country','region','measure','Option1','Option2']] 
    return d3 


print old(data) 
print new(data1) 
print (new(data1) == old(data)).all() 
country True 
region  True 
measure True 
Option1 True 
Option2 True 
dtype: bool 
+0

おかげjezrael。確認してお知らせします。 – marupav

+0

私の側からの1つの質問は、d1 ['value'] = d1 ['value']というステートメントの2番目の前の値を取るスマートな方法ですか?fillna(method = 'ffill')私の最終的なデータに邪魔される並べ替えの順序のためです。 – marupav

+0

はい、 'melt'の前に' data ['default'] = data ['min'] 'を追加してから' fillna'を削除してください。それでは、解決策は速いです - 'In [73]:%timeit new(data1) ループ100回、ループ3回あたり8.06ミリ秒' – jezrael

関連する問題