2016-05-07 11 views
3

を組み合わせる:故障した注文シーケンスに - - 最後のものを除いてGROUPBY - 日時デフ()私はこのようになりますデータフレームを持っている追加の基準に

In [265]: df_2 
Out[265]: 
     A   ID   DATETIME ORDER_FAILED 
0 B-028 b76cd912ff 2014-10-08 13:43:27   True 
1 B-054 4a57ed0b02 2014-10-08 14:26:19  False 
2 B-076 1a682034f8 2014-10-08 14:29:01  False 
3 B-023 b76cd912ff 2014-10-08 18:39:34   True 
4 B-024 f88g8d7sds 2014-10-08 18:40:18   True 
5 B-025 b76cd912ff 2014-10-08 18:42:02   True 
6 B-026 b76cd912ff 2014-10-08 18:42:41  False 
7 B-033 b76cd912ff 2014-10-08 18:44:30   True 
8 B-032 b76cd912ff 2014-10-08 18:46:00   True 
9 B-037 b76cd912ff 2014-10-08 18:52:15   True 
10 B-046 db959faf02 2014-10-08 18:59:59  False 
11 B-053 b76cd912ff 2014-10-08 19:17:48   True 
12 B-065 b76cd912ff 2014-10-08 19:21:38  False 

私はすべての繰り返しをドロップする必要がありますが、「注文を失敗しました」 。 'ID'

  • によって識別されていない連続した注文はよりません'ORDER_FAILED' == True
  • を持っています -

    1. 同じユーザによって配置:A「配列」は、以下の基準を満たして失敗した受注のシリーズがある

      お互いから5分以上離れています。

      In [298]: df_2[df_2.ORDER_FAILED == True].sort_values(by='DATETIME').groupby('ID')['DATETIME'].diff().dt.total_seconds() 
      Out[298]: 
      0   NaN 
      3  17767.0 
      4   NaN 
      5  148.0 
      7  148.0 
      8  90.0 
      9  375.0 
      11  1533.0 
      Name: DATETIME, dtype: float64 
      

      、その後、これに到達するためにpd.joinを使用します:私は、これは次のように行うことができる期待していた

    In [302]: df_2 = df_2.join(df_tmp); df_2 
    Out[302]: 
         A   ID   DATETIME ORDER_FAILED  diff 
    0 B-028 b76cd912ff 2014-10-08 13:43:27   True  NaN 
    1 B-054 4a57ed0b02 2014-10-08 14:26:19  False  NaN 
    2 B-076 1a682034f8 2014-10-08 14:29:01  False  NaN 
    3 B-023 b76cd912ff 2014-10-08 18:39:34   True 17767.0 
    4 B-024 f88g8d7sds 2014-10-08 18:40:18   True  NaN 
    5 B-025 b76cd912ff 2014-10-08 18:42:02   True 148.0 
    6 B-026 b76cd912ff 2014-10-08 18:42:41  False  NaN 
    7 B-033 b76cd912ff 2014-10-08 18:44:30   True 148.0 
    8 B-032 b76cd912ff 2014-10-08 18:46:00   True  90.0 
    9 B-037 b76cd912ff 2014-10-08 18:52:15   True 375.0 
    10 B-046 db959faf02 2014-10-08 18:59:59  False  NaN 
    11 B-053 b76cd912ff 2014-10-08 19:17:48   True 1533.0 
    12 B-065 b76cd912ff 2014-10-08 19:21:38  False  NaN 
    

    しかし、これは残念ながら正解ではありません。注文7は、diff == NaNになるはずです。これは、一連の失敗した注文のうち、このユーザーによる注文が成功した後(注文は6)です。

    私は上記のdiffを計算している方法が間違っていることを認識しており、成功した注文のたびにカウンタをリセットする方法は見つけられませんでした。

    希望正しい結果は次のようになります。

    In [303]: df_2 
    Out[303]: 
         A   ID   DATETIME ORDER_FAILED  diff 
    0 B-028 b76cd912ff 2014-10-08 13:43:27   True  NaN 
    1 B-054 4a57ed0b02 2014-10-08 14:26:19  False  NaN 
    2 B-076 1a682034f8 2014-10-08 14:29:01  False  NaN 
    3 B-023 b76cd912ff 2014-10-08 18:39:34   True 17767.0 
    4 B-024 f88g8d7sds 2014-10-08 18:40:18   True  NaN 
    5 B-025 b76cd912ff 2014-10-08 18:42:02   True 148.0 
    6 B-026 b76cd912ff 2014-10-08 18:42:41  False  NaN ## <- successful order 
    7 B-033 b76cd912ff 2014-10-08 18:44:30   True  NaN ## <- since this is the first failed order in this sequence of failed orders 
    8 B-032 b76cd912ff 2014-10-08 18:46:00   True  90.0 
    9 B-037 b76cd912ff 2014-10-08 18:52:15   True 375.0 
    10 B-046 db959faf02 2014-10-08 18:59:59  False  NaN 
    11 B-053 b76cd912ff 2014-10-08 19:17:48   True 1533.0 
    12 B-065 b76cd912ff 2014-10-08 19:21:38  False  NaN 
    

    この後、私はこのようなものでdiff > 300注文を単にマークになります。それを意味

    >> df_2.ix[df_2['diff'] > 300, 'remove_flag'] = 1 
    >> df_2.groupby('ID')['remove_flag'].shift(-1) ## <- adjust flag to mark the previous order in the sequence 
    >> df_2 = df_2[df_2.remove_flag != 1] 
    

    、最終的には、保管または廃棄すべき注文は以下の通りです。

    >> df_2 
         A   ID   DATETIME ORDER_FAILED  diff 
    0 B-028 b76cd912ff 2014-10-08 13:43:27   True  NaN ## STAYS - Failed, but gap to next failed by same user is greater than 5 minutes 
    1 B-054 4a57ed0b02 2014-10-08 14:26:19  False  NaN ## STAYS - successful order 
    2 B-076 1a682034f8 2014-10-08 14:29:01  False  NaN ## STAYS - successful order 
    3 B-023 b76cd912ff 2014-10-08 18:39:34   True 17767.0 ## DISCARD - The next failed order by the same user is only 148 seconds away (less than 5 minutes) 
    4 B-024 f88g8d7sds 2014-10-08 18:40:18   True  NaN ## STAYS - successful order 
    5 B-025 b76cd912ff 2014-10-08 18:42:02   True 148.0 ## STAYS - last in this sequence of failed orders by this user 
    6 B-026 b76cd912ff 2014-10-08 18:42:41  False  NaN ## STAYS - successful order 
    7 B-033 b76cd912ff 2014-10-08 18:44:30   True  NaN ## DISCARD - The next failed order by the same user is only 90 seconds away (less than 5 minutes) 
    8 B-032 b76cd912ff 2014-10-08 18:46:00   True  90.0 ## STAYS - next failed order by the same user is more than 5 minutes away 
    9 B-037 b76cd912ff 2014-10-08 18:52:15   True 375.0 ## STAYS - More than 5 minutes away from previous failed order by the same user 
    10 B-046 db959faf02 2014-10-08 18:59:59  False  NaN ## STAYS - Successful order 
    11 B-053 b76cd912ff 2014-10-08 19:17:48   True 1533.0 ## STAYS - too long since last failed order by this same user 
    12 B-065 b76cd912ff 2014-10-08 19:21:38  False  NaN ## STAYS - Successful order 
    

    ご協力いただきありがとうございます。ありがとうございます!

  • +0

    注文3はNaNではないのはなぜですか?注文が正常に完了した後も最初に失敗した注文ですか? – Evert

    +0

    "最後の1つを除いて、すべてのリピート"失敗した注文 "を削除する必要があります:つまり、失敗した注文のすべてのシーケンスのうち、最後の行を保持したい、または注文が失敗した場合は、(完全な)最後のシーケンスを保持しますか? – Evert

    +0

    前の**が同じユーザー**(注文「0」)によって実際には失敗した注文であるため、「3」は「NaN」ではありません。 – Thanos

    答えて

    1

    私はIDとDATETIME(昇順)でソートしてから始めましょう:私が正しく理解していれば、私たちは次の「によって(以下の条件の組み合わせを満たすすべての注文を削除する必要があり、

    df1 = df.sort_values(by = ['ID','DATETIME']) 
    

    今) "次の行に「私は理解":

    • 次の順序は

    • 01失敗

    • 失敗したため

    • 順序と次の時間差は、ほとんど300の

    • (及びさらに)でIDは次のIDと同じである(そうでなければ、それは非常に最後の順番であった)

    私の考えは簡単です:適切な列を追加して、各行にこれらの条件を評価するために必要なすべてのデータが含まれるようにします。

    この1つは、「次のID」と「次の順番」のフィールドを追加します。

    df1[['Next_ID','Next_ORDER_FAILED']] = df1[['ID','ORDER_FAILED']].shift(-1) 
    

    とこの1つは次の順に時間差を担当します。

    df1['diff'] = -df1['DATETIME'].diff(-1).dt.total_seconds() 
    

    (周期= -1の関連する差は負であり、したがって負の符号となる)。

    私は残りの部分はすでにかなり簡単だと思います。

    更新:ところで、私たちも、データフレームに新しい列を追加することなく、ブール値マスクを作成することができますが:

    mask = (df1['ORDER_FAILED'] == True) and (df1['ORDER_FAILED'].shift(-1) == True) and ... 
    

    UPDATE

    への本当の必要はありませんIDで注文すると、groupby()が正しく使用されていれば、全体的な解決策は実際にはややクリーナーになります。上記の提案の後に、最後にどのように行われたかを示します。

    In [478]: df_3 
    Out[478]: 
         A   ID   DATETIME ORDER_FAILED 
    0 B-028 b76cd912ff 2014-10-08 13:43:27   True 
    1 B-054 4a57ed0b02 2014-10-08 14:26:19  False 
    2 B-076 1a682034f8 2014-10-08 14:29:01  False 
    3 B-023 b76cd912ff 2014-10-08 18:39:34   True 
    4 B-024 f88g8d7sds 2014-10-08 18:40:18   True 
    5 B-025 b76cd912ff 2014-10-08 18:42:02   True 
    6 B-026 b76cd912ff 2014-10-08 18:42:41  False 
    7 B-033 b76cd912ff 2014-10-08 18:44:30   True 
    8 B-032 b76cd912ff 2014-10-08 18:46:00   True 
    9 B-037 b76cd912ff 2014-10-08 18:52:15   True 
    10 B-046 db959faf02 2014-10-08 18:59:59  False 
    11 B-053 b76cd912ff 2014-10-08 19:17:48   True 
    12 B-065 b76cd912ff 2014-10-08 19:21:38  False 
    
    In [479]: df_3['NEXT_FAILED'] = df_3.sort_values(by='DATETIME').groupby('ID')['ORDER_FAILED'].shift(-1) 
    
    In [480]: df_3['SECONDS_TO_NEXT_ORDER'] = -df_3.sort_values(by='DATETIME').groupby('ID')['DATETIME'].diff(-1).dt.total_seconds() 
    
    In [481]: condition = (df_3.NEXT_FAILED == True) & (df_3.ORDER_FAILED == True) & (df_3.SECONDS_TO_NEXT_ORDER <= 300) 
    
    In [482]: df_3[~condition].drop(['NEXT_FAILED','SECONDS_TO_NEXT_ORDER'], axis=1) 
    Out[482]: 
         A   ID   DATETIME ORDER_FAILED 
    0 B-028 b76cd912ff 2014-10-08 13:43:27   True 
    1 B-054 4a57ed0b02 2014-10-08 14:26:19  False 
    2 B-076 1a682034f8 2014-10-08 14:29:01  False 
    4 B-024 f88g8d7sds 2014-10-08 18:40:18   True 
    5 B-025 b76cd912ff 2014-10-08 18:42:02   True 
    6 B-026 b76cd912ff 2014-10-08 18:42:41  False 
    8 B-032 b76cd912ff 2014-10-08 18:46:00   True 
    9 B-037 b76cd912ff 2014-10-08 18:52:15   True 
    10 B-046 db959faf02 2014-10-08 18:59:59  False 
    11 B-053 b76cd912ff 2014-10-08 19:17:48   True 
    12 B-065 b76cd912ff 2014-10-08 19:21:38  False 
    

    OPによる説明に従って、正しい注文が削除されました!

    +0

    それは良い提案のセット、時間と努力のおかげでありました。私は最終的な解決策のための編集のための提案をしています。再度、感謝します! – Thanos

    +0

    @Thanosようこそ。お役に立てて嬉しいです。 – ptrj

    関連する問題