2016-12-09 5 views
0

最初のデータフレーム:inj_2014(35040,991)。列参照はEANと呼ばれます。3つのデータフレームでループを最適化するのに役立つ

  Date     541448860005060119 541448860003851078 ... 
0   2014-01-01 00:00:00     0.0    0.0 
1   2014-01-01 00:15:00     0.1    0.0 
... 

第2のデータフレーム:db(1125,17)。ここで、EANは1つの列に再編成されます。契約仕様に対応しているため991以上の行があります:契約が2014年2月に終了し、2014年3月に再び開始されると、dfに2行があります。 sdとedの列は、開始日と終了日に対応します。

    EAN   sd   ed ... 
0 541448860008422181 2014-07-02 2017-01-03 
1 541449200002077458 2012-01-04 2014-05-07 
... 

第3のデータフレーム:価格(1125,9)。数(すなわち、注射を掛け:基本的に各EANは年間を通じて変化(Q1-Q2-Q3-Q4)と時間(ピーク・オフピーク)

 Q1_peak Q1_off_peak ... Q4_off_peak     EAN 
0 82.0264  56.9196   61.9826 541448860008422181 
1 85.2736  57,8456   58,7564 541449200002077458 
... 

は私が何をしたいのかという、異なる価格の仕様を持っています)価格でinj_2014内と考慮して、新しいデータフレームにそれを置く:

  • 注入は日付が契約の範囲内にない場合に計算(または0を返すべきではないという事実)
  • 2つの異なる契約が同じEANを持つ可能性があるため、2つの異なる列が出力でなければならないという事実より最近の契約のための一例EAN_1)
  • 注入を乗じすべきで価格が、私はすでにいくつかの参考になった機能を書いた両方の日付とEAN

に依存しているという事実:

def in_contrat(date, sd, ed): 
    '''True if date within date limits''' 
    if sd < date < ed: 
     return True 
    else: 
     return False 

def price_name(date, dates_2014): #dates_2014 = list of the quarter limit dates 
    '''returns price name corresponding to the given date''' 
    if date < date_2014[1]: 
     if peak(date): 
      return 'Q1_peak' 
     else: 
      return 'Q1_off_peak' 
    elif date < date_2014[2]: 
     if peak(date): 
      return 'Q2_peak' 
    ... 

def in_contrat(date, sd, ed): 
    '''True if date within date limits''' 
    if sd < date < ed: 
     return True 
    else: 
     return False 

def get_index(df, test): 
    '''returns list with index occurences of the specific EAN number in the db''' 
    index = [] 
    for i in range(len(df)): 
     if df['EAN'][i] == test: 
      index.append(i) 
    return index 

は、だから私は私のマスター関数を記述しようとしたこの材料で:

def daily_calculation(inj_2014, db, prices): 
    list_EAN = [] 
    for i in range(len(db)): 
     EAN = db['EAN'][i] 
     if EAN not in list_EAN: 
      list_EAN.append(EAN) 
      index = get_index(prices, EAN)[0] 
     else : 
      index = get_index(prices, EAN)[1] 
     for j in range(len(inj_2014)): 
      date = inj_2014['Date'][j] 
      name = price_name(date, dates_2014) 
      EBIQ = prices[name][index] 
      valeur_injection = inj_2014[EAN][j]/4000 
      if in_contrat(date, db['sd'][i], db['ed'][i]) and inj_2014[EAN][j] != 0: 
       results.set_value(j, EAN, (valeur_injection)*EBIQ) 
      else: 
       results.set_value(j, EAN, 0) 
    return results 

そうなものがあり、これが動作しているようです。しかし、最初の列だけを計算するのにかかる時間を考えれば、結果を得るには80〜100時間かかりますし、間違っているかもしれません。私は数日の間違いを見つけて、間違って走るのを見つけることができます。しかし、数ヶ月ではありません。

このループを最適化する方法があることは確かです(私はすでに200時間から100時間に達することができました)。しかし、私はpython/pandas/etcでかなり新しく、自分でそれを最適化する経験はありません。これは一種の絶望的な呼び出しです。

答えて

0

詳細な情報がなくても正確な答えを書くのは難しいですが、ここでは試みます。 (価格のため、私は、ルックアップをお勧めします)dbと合併、

inj_stacked = inj_2014.set_index('Date') \ 
         .stack() \ 
         .reset_index(drop=False) \ 
         .rename(columns={'level_1': 'EAN', 0: 'injection'}) 

第二

まず、新しい列に列名を置くためにinj_2014EANと呼ばれるスタック

inj_stacked = inj_stacked.merge(db, on='EAN', how='outer') 

注:異なる値のhowを試してみる必要があります。上記は私の最高の推測です。

第三に、あなたが適用操作をベクトル:

inj_stacked['in_contrat'] = (inj_stacked['Date'] > inj_stacked['sd']) \ 
          & (inj_stacked['Date'] < inj_stacked['ed']) 

inj_stacked['price_name'] = inj_stacked['Date'].apply(price_name, 
                 args=(dates_2014,)) 

第四に、ルックアップ価格:

inj_stacked['price'] = prices.set_index('EAN').lookup(
    inj_stacked['EAN'], 
    inj_stacked['price_name']).values 

これは、すべてのテストされ、必要に応じて、適応してください。

+0

ありがとうございます、私はすでにこれを試してみましょう! –

関連する問題