2 votes

pandas obtient le premier élément des valeurs contiguës pour effectuer la sessionisation, c'est-à-dire obtenir l'événement de début de session.

Comment puis-je trouver le premier élément d'une des sessions (pour chaque groupe) qui démarre une nouvelle série de valeurs continues ?

import pandas as pd
df = pd.DataFrame({'group':[1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,], 'value':[
    1,2,3,4,5,10,11, 15, 16,17,18,19,20, # 13
    21, 22,23,24,26,27.28,
    4,5,6, 8,9,10,11,12, 13,14
]})
display(df)

jusqu'à présent, je suis coincé ici :

df['shifted_value'] = df['value'].shift(-1)
df['difference_nect'] = df['shifted_value'] - df['value']

# this is obviously not yet correct - how can I get the first element (elemnt of 0 for each of the starting sessions)
df['session_element_index'] = df.groupby(['group']).cumcount()
df.head()

En SQL, j'utiliserais une fonction fenêtre et je comparerais les éléments précédents/suivants pour déterminer si une session commence/se termine. Existe-t-il une manière plus agréable et plus native de pandas de faire cela de manière vectorielle ?

1voto

jezrael Points 290608

Utilice DataFrameGroupBy.diff avec comparaison non égale 1 et filtrer dans boolean indexing :

df1 = df[df.groupby('group')['value'].diff().ne(1)]
print (df1)
    group  value
0       1   1.00
5       1  10.00
7       1  15.00
17      1  26.00
18      1  27.28
19      2   4.00
22      2   8.00

Si nécessaire, contre-colonne :

g = df.groupby('group')['value'].apply(lambda x: x.diff().ne(1).cumsum())
df['session_element_index'] = df.groupby(g).cumcount()
print (df.head(10))
   group  value  session_element_index
0      1    1.0                      0
1      1    2.0                      1
2      1    3.0                      2
3      1    4.0                      3
4      1    5.0                      4
5      1   10.0                      0
6      1   11.0                      1
7      1   15.0                      0
8      1   16.0                      1
9      1   17.0                      2

0voto

Corralien Points 6849

Comme la première approche :

out = df.groupby("group", as_index=False).value \
        .apply(lambda s: ((s - s.shift()) != 1.0).cumsum() \
        .drop_duplicates())

>>> out
0  0     1
   5     2
   7     3
   17    4
   18    5
1  19    1
   22    2
Name: value, dtype: int64

>>> out.index.get_level_values(1)
Int64Index([0, 5, 7, 17, 18, 19, 22], dtype='int64')

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X