Comment grouper DataFrame par une période de temps?

J'ai des données à partir de fichiers journaux et je voudrais regrouper les entrées d'une minute:

 def gen(date, count=10):
     while count > 0:
         yield date, "event{}".format(randint(1,9)), "source{}".format(randint(1,3))
         count -= 1
         date += DateOffset(seconds=randint(40))

 df = DataFrame.from_records(list(gen(datetime(2012,1,1,12, 30))), index='Time', columns=['Time', 'Event', 'Source'])

Df:

 Event  Source
 2012-01-01 12:30:00     event3  source1
 2012-01-01 12:30:12     event2  source2
 2012-01-01 12:30:12     event2  source2
 2012-01-01 12:30:29     event6  source1
 2012-01-01 12:30:38     event1  source1
 2012-01-01 12:31:05     event4  source2
 2012-01-01 12:31:38     event4  source1
 2012-01-01 12:31:44     event5  source1
 2012-01-01 12:31:48     event5  source2
 2012-01-01 12:32:23     event6  source1

J'ai essayé ces options:

  1. {[3] } est un niveau trop élevé et veut agréger.
  2. df.groupby(date_range(datetime(2012,1,1,12, 30), freq='Min', periods=4)) échoue avec exception.
  3. df.groupby(TimeGrouper(freq='Min')) fonctionne bien et renvoie un objet DataFrameGroupBy pour un traitement ultérieur, par exemple:

    grouped = df.groupby(TimeGrouper(freq='Min'))
    grouped.Source.value_counts()
    2012-01-01 12:30:00  source1    1
    2012-01-01 12:31:00  source2    2
                         source1    2
    2012-01-01 12:32:00  source2    2
                         source1    2
    2012-01-01 12:33:00  source1    1
    

Cependant, le TimeGrouper classe n'est pas documentée.

Quelle est la bonne façon de grouper par un point de temps? Comment puis-je regrouper les données par une minute et par la colonne Source, par exemple groupby([TimeGrouper(freq='Min'), df.Source])?

38
demandé sur Gabriel 2012-06-17 22:07:39

2 réponses

Vous pouvez grouper sur n'importe quel tableau/série de la même longueur que votre DataFrame --- même un facteur calculé qui n'est pas réellement une colonne du DataFrame. Donc, pour grouper par minute, Vous pouvez faire:

df.groupby(df.index.map(lambda t: t.minute))

Si vous voulez grouper par minute et autre chose, mélangez simplement ce qui précède avec la colonne que vous voulez utiliser:

df.groupby([df.index.map(lambda t: t.minute), 'Source'])

Personnellement, je trouve utile d'ajouter simplement des colonnes au DataFrame pour stocker certaines de ces choses calculées (par exemple, une colonne "Minute") si je veux les regrouper souvent, car rend le code de regroupement moins verbeux.

, Ou vous pouvez essayer quelque chose comme ceci:

df.groupby([df['Source'],pd.TimeGrouper(freq='Min')])
42
répondu BrenBarn 2015-09-16 13:15:45

Puisque la réponse originale est plutôt ancienne et que les pandas ont introduit périodes une solution différente est de nos jours:

df.groupby(df.index.to_periods('T'))

De plus, vous pouvez rééchantillonner

df.resample('T')
2
répondu Quickbeam2k1 2018-04-20 12:40:45