2
votes

Extraire des groupes de valeurs consécutives d'une taille supérieure à la taille spécifiée

J'essaie de trouver dans un dataframe s'il y a au moins X opérations consécutives (j'ai déjà inclus une colonne "Filter_OK" qui calcule si la ligne répond aux critères) et d'extraire ce groupe de lignes. / pre>

Pour cet exemple, si je recherche 4 opérations.
SORTIE DÉSIRÉE:

    TRN     TRN_DATE    FILTER_OK  
4   9652    06/04/2017  20:32:00    True 
5   965     07/04/2017  12:52:00    True
6   752     10/04/2017  17:40:00    True
7   9541    10/04/2017  19:29:00    True
8   7452    11/04/2017  12:20:00    True

Comment puis-je sous-définir les opérations dont j'ai besoin?


0 commentaires

4 Réponses :


1
votes

Vous pouvez le faire en utilisant cumsum , suivi de groupby et de transform:

v.groupby(v).transform('size').ge(4) & df['FILTER_OK']

0    False
1    False
2    False
3    False
4     True
5     True
6     True
7     True
8     True
9    False
Name: FILTER_OK, dtype: bool

Détails

Tout d'abord, utilisez cumsum pour séparer les lignes en groupes:

v.groupby(v).transform('size')

0    3
1    3
2    3
3    6
4    6
5    6
6    6
7    6
8    6
9    1
Name: FILTER_OK, dtype: int64

v.groupby(v).transform('size').ge(4)

0    False
1    False
2    False
3     True
4     True
5     True
6     True
7     True
8     True
9    False
Name: FILTER_OK, dtype: bool

Ensuite, trouvez la taille de chaque groupe, puis déterminez quels groupes ont au moins X lignes (dans votre cas, 4):

v = (~df.FILTER_OK).cumsum()
v

0    0
1    0
2    0
3    1
4    1
5    1
6    1
7    1
8    1
9    2
Name: FILTER_OK, dtype: int64

ET ce masque avec "FILTER_OK" pour nous assurer que nous ne prenons que les lignes valides qui correspondent aux critères.

v = (~df.FILTER_OK).cumsum()
df[v.groupby(v).transform('size').ge(4) & df['FILTER_OK']]

    TRN            TRN_DATE  FILTER_OK
4  9652 2017-06-04 20:32:00       True
5   965 2017-07-04 12:52:00       True
6   752 2017-10-04 17:40:00       True
7  9541 2017-10-04 19:29:00       True
8  7452 2017-11-04 12:20:00       True


1 commentaires

Cela fait en fait partie d'une opération "group by" (par colonne CRD). S'il y a deux groupes consécutifs de lignes (Crd 111 et 333) et que le deuxième groupe de lignes ne remplit pas la condition (pas 4 consécutifs True), la première ligne du groupe est incluse (la ligne en gras), alors qu'elle ne devrait pas 't



1
votes

Ceci considérera également 4 False

s=df.FILTER_OK.astype(int).diff().ne(0).cumsum()
df[s.isin(s.value_counts().loc[lambda x : x>4].index)]
Out[784]: 
    TRN            TRN_DATE  FILTER_OK
4  9652  06/04/201720:32:00       True
5   965  07/04/201712:52:00       True
6   752  10/04/201717:40:00       True
7  9541  10/04/201719:29:00       True
8  7452  11/04/201712:20:00       True

consécutifs


0 commentaires

0
votes

Une des options possibles est d'utiliser itertools.groupby appelé sur la source df.values ​​.

Une différence importante de cette méthode, par rapport à pd.groupby est que si la clé de groupe change, un nouveau groupe est créé.

Vous pouvez donc essayer le code suivant:

import pandas as pd
import itertools

# Source DataFrame
df = pd.DataFrame(data=[
    [ 5153, '04/04/2017 11:40:00', True ], [ 7542, '04/04/2017 17:18:00', True ],
    [  875, '04/04/2017 20:08:00', True ], [   74, '05/04/2017 20:30:00', False ],
    [ 9652, '06/04/2017 20:32:00', True ], [  965, '07/04/2017 12:52:00', True ],
    [  752, '10/04/2017 17:40:00', True ], [ 9541, '10/04/2017 19:29:00', True ],
    [ 7452, '11/04/2017 12:20:00', True ], [ 9651, '12/04/2017 13:57:00', False ]],
    columns=[ 'TRN', 'TRN_DATE', 'FILTER_OK' ])
# Work list 
xx = []
# Collect groups for 'True' key with at least 5 members
for key, group in itertools.groupby(df.values, lambda x: x[2]):
    lst = list(group)
    if key and len(lst) >= 5:
        xx.extend(lst)
# Create result DataFrame with the same column names
df2 = pd.DataFrame(data=xx, columns=df.columns)


0 commentaires

0
votes

Cela fait en fait partie d'une opération "group by" (par colonne CRD). S'il y a deux groupes consécutifs de lignes (Crd 111 et 333) et que le deuxième groupe de lignes ne remplit pas la condition (pas 4 consécutifs True), la première ligne du groupe est incluse (la ligne en gras), alors qu'elle ne devrait pas 't

CRD     TRN     TRN_DATE            FILTER_OK

0    111    5153    04/04/2017 11:40:00     True

1       111     7542    04/04/2017 17:18:00     True

2       256     875     04/04/2017 20:08:00     True

3       365     74      05/04/2017 20:30:00     False

4       111     9652    06/04/2017 20:32:00     True

5       111     965     07/04/2017 12:52:00     True

6       111     752     10/04/2017 17:40:00     True

7       111     9541    10/04/2017 19:29:00     True

**8     333     7452    11/04/2017 12:20:00     True**

9       333     9651    12/04/2017 13:57:00     False

10      333     961     12/04/2017 13:57:00     False

11      333     871     12/04/2017 13:57:00     False

Actual output:

    CRD  TRN     TRN_DATE          FILTER_OK  
4   111  9652    06/04/2017 20:32:00      True

5   111  965     07/04/2017 12:52:00      True

6   111  752     10/04/2017 17:40:00      True

7   111  9541    10/04/2017 19:29:00      True

**8   333  7452    11/04/2017 12:20:00      True**

Desired output:

    CRD  TRN     TRN_DATE          FILTER_OK  
4   111  9652    06/04/2017 20:32:00      True

5   111  965     07/04/2017 12:52:00      True

6   111  752     10/04/2017 17:40:00      True

7   111  9541    10/04/2017 19:29:00      True


0 commentaires