2017-08-30 5 views
2

私は以下のpdデータフレームを持っています。 Iは、上記の例でパンダで列間の日付を補間する

x: x1 
independent = [d1, d2, d3] 
dependent = [v1, v2, v3] 

を補間することにより、列X2を算出したい

import pandas as pd 

df = pd.DataFrame([pd.datetime(2016,1,1), pd.datetime(2016,2,1)], columns = ['d1']) 
df['d2'] = [pd.datetime(2016,1,5), pd.datetime(2016,2,10)] 
df['d3'] = [pd.datetime(2016,1,10), pd.datetime(2016,2,20)] 
df['v1'], df['v2'], df['v3'] = [1,10], [5, 100], [5, 100] 
df['x1'] = [pd.datetime(2016,1,2), pd.datetime(2016,2,13)] 


      d1   d2   d3 v1 v2 v3   x1 
0 2016-01-01 2016-01-05 2016-01-10 1 5 5 2016-01-02 
1 2016-02-01 2016-02-10 2016-02-20 10 100 100 2016-02-13 

、x2は行0 2、私が使用して考えることができる行1

100であるべきですdp.iterrows()、スライス[d1-d3]、[v1-v3]を使用して、np.interpを使用しますが、日付を浮動小数点に変換する必要があるため、 (np.interpは浮動小数点のリストのみを取ります)。

Pandasでは、よりクリーンでベクトル化されたアプローチが必要ですか?

答えて

1

パンダがIVとDVとして特定の列を使用して補間できるかどうかわかりません。しかし、タイムスタンプを1つのシリーズと考えると、あなたが望むものを手に入れることができます。

少しシャッフルして、interpolate(method='time')のデータフレームを再フォーマットして元のフォーマットに戻すことができます。あなたのサンプルデータフレームから開始して、空のx2に追加します。

import numpy as np 
df['x2'] = np.nan 

df 
      d1   d2   d3 v1 v2 v3   x1 x2 
0 2016-01-01 2016-01-05 2016-01-10 1 5 5 2016-01-02 NaN 
1 2016-02-01 2016-02-10 2016-02-20 10 100 100 2016-02-13 NaN 

今longに広いからスイング、そしてちょうど2つの列の中に凝縮し、dvxすることは今のdvクラブで名誉会員を取得します)。指標として、実際のカラム名を保存します。

pairs = [('d1','v1'), ('d2','v2'), ('d3','v3'), ('x1','x2')] 
df2 = pd.concat(
    (df[[d, v]].rename(index=lambda i: d, 
         columns=lambda x: 'd' if (x[0]=='d') | (x=='x1') else 'v') for d, v in pairs)) 

df2 

      d  v 
d1 2016-01-01 1.0 
d1 2016-02-01 10.0 
d2 2016-01-05 5.0 
d2 2016-02-10 100.0 
d3 2016-01-10 5.0 
d3 2016-02-20 100.0 
x1 2016-01-02 NaN 
x1 2016-02-13 NaN 

我々は時間に基づいてinterpolateにしたいので、私たちはソート日付で、インデックスにタイムスタンプを移動し、補間を実行します:

df3 = (df2.reset_index() 
      .set_index(pd.to_datetime(df2.d)) 
      .drop('d', 1) 
      .sort_index() 
      .interpolate(method="time") 
      .sort_values('index') 
    ) 

df3 
      index  v 
d      
2016-01-01 d1 1.0 
2016-02-01 d1 10.0 
2016-01-05 d2 5.0 
2016-02-10 d2 100.0 
2016-01-10 d3 5.0 
2016-02-20 d3 100.0 
2016-01-02 x1 2.0 
2016-02-13 x1 100.0 

補間は、OP期待出力ごとに正しいです。今度は、データフレームを元の形に戻すだけです。私たちは、奇数/偶数行番号に基づいて、バック0/1にインデックスを設定し、その後pivot()を使用してこれを実行します。

df4 = df3.reset_index().rename(index=lambda x: int(x%2)).pivot(columns='index') 
df4.columns = df4.columns.droplevel(0) 
iv, dv = zip(*pairs) 
df4.columns = iv + dv 

df4 
      d1   d2   d3   x1 v1  v2  v3  x2 
0 2016-01-01 2016-01-05 2016-01-10 2016-01-02 1.0 5.0 5.0 2.0 
1 2016-02-01 2016-02-10 2016-02-20 2016-02-13 10.0 100.0 100.0 100.0 

途中で物事を再形成するステルスの方法が、キー直感があるかもしれませんここで、Pandasは、適切なフォーマットが与えられていれば、時間を基準として欠損値を補間することになります。

UPDATE(コメントあたり)
補間ごとの行が発生する必要がある場合、我々はapply()と、上記と同様の方法を使用することができます。

def custom_interp(row, pairs): 
    data = pd.concat(
     (pd.DataFrame(row[[d, v]]).rename(index=lambda x: 'd' if (x[0] == 'd') | (x == 'x1') else 'v', 
              columns=lambda x: d) for d, v in pairs), 
     axis=1).T.reset_index() 
    data = (data.set_index(pd.to_datetime(data.d)) 
       .drop('d', 1) 
       .sort_index() 
      ) 
    data.v = data.v.astype(float) 
    data = data.interpolate(method='time').reset_index() 
    data.index = np.repeat(row.name, len(data.index)) 
    data = data.pivot(columns='index') 
    data.columns = data.columns.droplevel(0) 
    return data.values[0] 

df.apply(custom_interp, args=(pairs,), axis=1) 

      d1   d2   d3   v1 v2  v3  x1  x2 
0 2016-01-01 2016-01-05 2016-01-10 2016-01-02 1.0 5.0 5.0 2.0 
1 2016-02-01 2016-02-10 2016-02-20 2016-02-13 10.0 100.0 100.0 100.0 
+0

おかげ。アイデアのように、補間は行ごとに行う必要があります。あなたの例のdf2はすべての行からd'とsを組み合わせます。 –

+0

指定したデータ例では、各行の日付は、行全体で重複しない期間を形成しました。この種の重複が発生する場合がありますか? –

+0

はい、申し訳ありませんが、私の例は悪いです。重複があります。より良い例は、すべての 'Feb'を1行目の 'Jan'に置き換えることです。 –

関連する問題