2017-02-03 12 views
2

私は、次のことをしようとしている非正規のタイムスタンプによって索引付けされた非常にまばらなデータフレーム(1行につき1つの非ゼロ値のみ)を持っています。パンダの行フィルタ/クロス集計をローリングするには?

与えられた列の0以外の値について、与えられたtimedelta内の他の列の他の非ゼロ値の数を数えたいと思います。ある意味では、rolling cross_tabのようなものを計算しようとしています。

これまでの私のソリューションは、スライシングとローリングを使用してこれを行う方法を理解していないので、醜いですし、遅いです。

delta = 1 
values = pd.DataFrame(0,index= df.columns,columns= df.columns) 
for j in df.columns: 
    for i in range(len(df[df[j]!=0].index)-1): 
     #min is used to avoid overlapping 
     values[j] +=df[(df.index<min((df[df[j]!=0].index + pd.tseries.timedeltas.to_timedelta(delta, unit='h'))[i],df[df[j]!=0].index[i+1]))&(df.index>=df[df[j]!=0].index[i])].astype(bool).sum() 
values = values.T 

とおもちゃ例のデータフレームである:

df = pd.DataFrame.from_dict({"2016-01-01 10:00.00":[0,1], 
         "2016-01-01 10:30.00":[1,0], 
         "2016-01-01 12:00.00":[0,1], 
         "2016-01-01 14:00.00":[1,0]}, 
         orient="index") 
df.columns=['a','b'] 
df.index = pd.to_datetime(df.index) 

         a b 
2016-01-01 10:00:00 0 1 
2016-01-01 10:30:00 1 0 
2016-01-01 12:00:00 0 1 
2016-01-01 14:00:00 1 0 

所望の出力は(カウントがはtimedeltaに依存して)次のようになります。それはのようなものが見えます

 a  b 
a  1  0 
b  1  1 

答えて

1

正確に何をしたいかを伝えるのは難しいです。しかし、それはこのように聞こえました

私は新しい機能パンダ0.19を使いたいです。時間認識rolling。それを使用するには、ソートされたインデックスが必要です。

d1 = df.sort_index() 

ここで、プラスまたはマイナス1時間以内にカウントしたいとします。インデックスのすべての要素に2時間を追加することから始めましょう。次に、4時間を振り返りながら、ロールオーバーします。これは、元の指数に対して2時間と2時間後を楽しみにしているようです。

d2 = d1.rolling('4H').sum() 
d2.index = d2.index - pd.offsets.Hour(2) 
d2 

         a b 
2016-01-01 10:00:00 0.0 1.0 
2016-01-01 10:30:00 1.0 1.0 
2016-01-01 12:00:00 1.0 2.0 
2016-01-01 14:00:00 2.0 1.0 
+0

ありがとうございました。 – alkaet

+0

タイムスタンプはソートされています(私が述べたはずです)。 これは私が望むものとは少し異なります。私は少し明確にしようとします。 の変更の1時間以内に発生する列bの変化の数をカウントしたいと思います。私の例では、aが1時間以内に1回変化します - 行b列aの出力でカウントされます(対角線は元のデータフレームの各列の値の変更の数だけ)。 あなたの答えは、正しく理解すれば、1つの列の値のローリング合計に過ぎません。 – alkaet

関連する問題