2016-05-04 9 views
4

各行にイベントに関する情報が含まれ、イベントが成功したかどうかを示すデータフレームがあります。私は非成功イベント間のデルタを計算したい、私はフィールド間のdiffを計算する方法を知っているが、フィルタを使用するときは分からない。Pandasを使用してフィルタを使用して値の差を計算します

私のデータフレームは、このような構造を持っている:私が欲しいもの

 Timestamp  Status   
    0 2012-01-01  OK 
    1 2012-01-02  OK 
    2 2012-01-03  FAIL 
    3 2012-01-05  OK 
    4 2012-01-06  OK 
    5 2012-01-07  FAIL 

は、次のようにこのようsomtethin、失敗するまで、各行のための時間を計算することである。

 Timestamp  Status  Days_until_next_fail    
    0 2012-01-01  OK   2 
    1 2012-01-02  OK   1 
    2 2012-01-03  FAIL  0 
    3 2012-01-05  OK   2 
    4 2012-01-06  OK   1 
    5 2012-01-07  FAIL  0 

私はこの試みた:

df['days_until_next_failure'] = df.Timestamp - df[(df.Status == '1')].Timestamp(+1) 

しかし、これはNaTを返します。ドキュメントには、フィルタリングと使用を適用するためのものは見つかりませんシフト。 1つの選択肢は、最後からデータフレームを反復することですが、それは少し非効率的です。

+1

これは 'cumsum'の仕事です...あなたが望むものを得るには、数行のコードが必要です。 ( 'cumsum'はデータ内のある点まで何個あるかを教えてくれます) –

答えて

1

以下は、日の与えインス最後のではなく、次までの日数よりも、失敗:

is_fail = (df.Status != 'OK') 
cumulative_fails = is_fail.cumsum() 
fail_idx, = is_fail.nonzero() 
days_since_last_fail = arange(len(is_fail)) 
days_since_last_fail[fail_idx[0]:] -= fail_idx[cumulative_fails[fail_idx[0]:]-1] 

あなたが正しいバージョンをしたい場合は、あなた自身のためにこれを適応させることができ、または多分ちょうど開始時と終了時に元の配列を反転。

+0

申し訳ありません、仕事をしています。 – jezrael

+0

ええ、私は実際にそれをPythonで試して修正しようとしています。 –

+0

@jezrael - それは今すぐ動作するはずです –

1

ソリューション列Timestamp場合は、ソートされ、毎月のすべての日が含まれます:

あなたはこのSerieと集計cumcountによってgroupbyその後、cumsumすることにより、データの最初の発見グループを試すことができます。あなたは0によってそうfillnaNaNを取得し、astypeによって整数に出力列を変換:

#reverse ordering 
df = df[::-1] 

print (df.Status == 'FAIL').astype(int).cumsum() 
5 1 
4 1 
3 1 
2 2 
1 2 
0 2 
Name: Status, dtype: int32 

#filter and get ordering of colums 
df['Days_until_next_fail'] = df[df.Status=='OK'] 
           .groupby((df.Status == 'FAIL').astype(int).cumsum()) 
           .cumcount() + 1 

#replace NaN by 0, convert values to integer        
df['Days_until_next_fail'] = df['Days_until_next_fail'].fillna(0).astype(int) 
#ordering to original 
df.sort_index(inplace=True) 
print df 
    Timestamp Status Days_until_next_fail 
0 2012-01-01  OK      2 
1 2012-01-02  OK      1 
2 2012-01-03 FAIL      0 
3 2012-01-05  OK      2 
4 2012-01-06  OK      1 
5 2012-01-07 FAIL      0 

より一般的な解決策、(すべての日付をソートする必要がある):

print df 
    Timestamp Status 
0 2011-12-28  OK 
1 2012-01-02  OK 
2 2012-01-03 FAIL 
3 2012-01-05  OK 
4 2012-01-06  OK 
5 2012-01-07 FAIL 

#reverse ordering 
df = df[::-1] 

df['days_until_next_failure'] = df.groupby((df.Status == 'FAIL').astype(int).cumsum()) 
            .apply(lambda x: x.iloc[0][0] - x.Timestamp) 
            .reset_index(level=0, drop=True) 

print df.sort_index() 
    Timestamp Status days_until_next_failure 
0 2011-12-28  OK     6 days 
1 2012-01-02  OK     1 days 
2 2012-01-03 FAIL     0 days 
3 2012-01-05  OK     2 days 
4 2012-01-06  OK     1 days 
5 2012-01-07 FAIL     0 days 

をあなたはから列を変換する必要がある場合timedeltaintへ:

df['fail_days'] = df.groupby((df.Status == 'FAIL').astype(int).cumsum()) 
        .apply(lambda x: ((x.iloc[0][0] - x.Timestamp)/np.timedelta64(1, 'D')) 
             .astype(int)) 

        .reset_index(level=0, drop=True) 

print df.sort_index() 
    Timestamp Status fail_days 
0 2011-12-28  OK   6 
1 2012-01-02  OK   1 
2 2012-01-03 FAIL   0 
3 2012-01-05  OK   2 
4 2012-01-06  OK   1 
5 2012-01-07 FAIL   0 
+1

' globalby 'の出力を使ってdf [' Timestamp ']にインデックスを付けるだけで、 'cumsum' –

+0

申し訳ありませんが、私は理解できません。その場合には – jezrael

+0

私は自分の答えを提供する必要があります! (部分的に私のせいで説明できないのは間違いだと思う) –

関連する問題