4 votes

Fractionnement des données d'appel en intervalles de 15 minutes dans pandas

Je suis nouveau dans python et pandas et même si j'ai fait beaucoup de recherches sur les intervalles, je n'ai pas pu trouver de solution à mon problème, j'espère que quelqu'un pourra m'aider

Voici un échantillon de mon DF

df = pd.DataFrame(
    data=[['Mel Gibson', 'German', '2021-9-23 14:22:38', 301 ],
          ['Jim Carrey', 'German', '2021-9-23 14:27:39', 1041 ],
          ['Mel Gibson', 'German','2021-9-24 13:33:22',12]],
    columns=['specialist', 'Language', 'Interval Start', 'status_duration']
)
df['Interval Start'] = pd.to_datetime(df['Interval Start'])

Ce que je veux faire, c'est transformer la durée des statuts en intervalles de 15 minutes et les regrouper par spécialiste et par jour.

Le résultat que je souhaite obtenir devrait être le suivant :

df = pd.DataFrame(
    data=[['Mel Gibson', 'German', '2021-9-23 14:15:00', 301 ],
          ['Jim Carrey', 'German', '2021-9-23 14:15:00', 141 ],
          ['Jim Carrey', 'German', '2021-9-23 14:30:00', 900 ],
          ['Mel Gibson', 'German','2021-9-24 13:30:00',12]],
    columns=['specialist', 'Language', 'Interval Start', 'status_duration']
)

En gros, je dois diviser les secondes de la durée de l'état en intervalles de 15 minutes jusqu'à ce qu'il ne reste plus de durée.

Edit :

Mes données d'origine sont les suivantes :

    df = pd.DataFrame(
            data=[['Mel Gibson', 'German', '2021-9-23 14:22:38', 301 ],
                  ['Mel Gibson', 'German', '2021-9-23 14:27:40', 4678 ],
                  ['Mel Gibson', 'German','2021-9-24 13:33:22',12]],
            columns=['specialist', 'Language', 'Interval Start', 'status_duration']
        )
        df['Interval Start'] = pd.to_datetime(df['Interval Start'])

Le code d'Henry me donne une sortie pour la première ligne seulement, la deuxième ligne est ignorée.

De même, si un appel a commencé à 10:35:00, l'intervalle (10:30-10:45) ne peut pas dépasser 600 secondes car il ne reste que 10 minutes avant le début de l'appel.

4voto

Henry Yik Points 9160

Une façon de faire est d'utiliser le quotient et le reste de status_duration , explode le résultat et enfin additionner le temps en secondes :

ref = (df.groupby(["specialist", "Language", pd.Grouper(key="Interval Start", freq="D")], as_index=False)
         .agg(status_duration=("status_duration", lambda d: [*([900]*(d.iat[0]//900)), d.iat[0]%900]),
              Interval=("Interval Start", "first"))
         .explode("status_duration"))

ref["Interval"] = ref["Interval"].dt.floor("15min")+pd.to_timedelta(ref.groupby(ref.index).cumcount()*900, unit="sec")

print (ref)

   specialist Language status_duration            Interval
0  Jim Carrey   German             900 2021-09-23 14:15:00
0  Jim Carrey   German             141 2021-09-23 14:30:00
1  Mel Gibson   German             301 2021-09-23 14:15:00
2  Mel Gibson   German              12 2021-09-24 13:30:00

1voto

buddemat Points 2030

Vous pouvez utiliser le dt.floor() pour l'arrondi :

df['Interval Start'] = df['Interval Start'].dt.floor("15min")

Résultat (basé sur vos données éditées) :

   specialist Language      Interval Start  status_duration
0  Mel Gibson   German 2021-09-23 14:15:00              301
1  Mel Gibson   German 2021-09-23 14:15:00             4678
2  Mel Gibson   German 2021-09-24 13:30:00               12

J'ai ensuite ajouté une colonne contenant le nombre d'intervalles attendus :

df['len'] = 1 + df['status_duration']//900

Résultat :

0  Mel Gibson   German 2021-09-23 14:15:00              301    1
1  Mel Gibson   German 2021-09-23 14:15:00             4678    6
2  Mel Gibson   German 2021-09-24 13:30:00               12    1

Vous pouvez alors utiliser numpy.repeat() pour dupliquer les rangées correspondantes et la compréhension de la liste avec timedelta() pour construire les intervalles correspondants.

import numpy as np
from datetime import timedelta

new_df = pd.DataFrame({'specialist': np.repeat(df['specialist'], df['len']),
                'Language': np.repeat(df['Language'], df['len']),
                'Interval Start': [el for sublist in [[x['Interval Start'] + timedelta(minutes=15*y) for y in range(0, x['len'])] for i, x in df.iterrows()] for el in sublist],
                'status_duration': [el for sublist in [([900]*(x['len']-1)+[x['status_duration']%900]) for i, x in df.iterrows()] for el in sublist]
})

Résultat :

   specialist Language      Interval Start  status_duration
0  Mel Gibson   German 2021-09-23 14:15:00              301
1  Mel Gibson   German 2021-09-23 14:15:00              900
1  Mel Gibson   German 2021-09-23 14:30:00              900
1  Mel Gibson   German 2021-09-23 14:45:00              900
1  Mel Gibson   German 2021-09-23 15:00:00              900
1  Mel Gibson   German 2021-09-23 15:15:00              900
1  Mel Gibson   German 2021-09-23 15:30:00              178
2  Mel Gibson   German 2021-09-24 13:30:00               12

Enfin, vous pouvez souhaiter réinitialiser l'index :

new_df = new_df.reset_index(drop=True)

Résultat :

   specialist Language      Interval Start  status_duration
0  Mel Gibson   German 2021-09-23 14:15:00              301
1  Mel Gibson   German 2021-09-23 14:15:00              900
2  Mel Gibson   German 2021-09-23 14:30:00              900
3  Mel Gibson   German 2021-09-23 14:45:00              900
4  Mel Gibson   German 2021-09-23 15:00:00              900
5  Mel Gibson   German 2021-09-23 15:15:00              900
6  Mel Gibson   German 2021-09-23 15:30:00              178
7  Mel Gibson   German 2021-09-24 13:30:00               12

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