Hoe kan ik DataFrame groeperen op een tijdsperiode?

Ik heb wat gegevens uit logbestanden en wil de gegevens per minuut groeperen:

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

Ik heb deze opties geprobeerd:

  1. df.resample('Min')is te hoog niveau en wil aggregeren.
  2. df.groupby(date_range(datetime(2012,1,1,12, 30), freq='Min',
    periods=4))
    mislukt met uitzondering.
  3. df.groupby(TimeGrouper(freq='Min'))werkt prima en retourneert een DataFrameGroupBy-object voor verdere verwerking, bijvoorbeeld:

    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
    

Echteris de klasse TimeGrouperniet gedocumenteerd.

Wat is de juiste manier om te groeperen op een tijdsperiode? Hoe kan ik de gegevens groeperen op een minuut EN op de kolom Bron, b.v. groupby([TimeGrouper(freq='Min'), df.Source])?


Antwoord 1, autoriteit 100%

Je kunt groeperen op elke array/reeks van dezelfde lengte als je DataFrame — zelfs een berekende factor die niet echt een kolom van het DataFrame is. Dus groeperen per minuut kun je doen:

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

Als je per minuut en iets anders wilt groeperen, meng dan het bovenstaande met de kolom die je wilt gebruiken:

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

Persoonlijk vind ik het handig om kolommen aan het DataFrame toe te voegen om sommige van deze berekende dingen op te slaan (bijvoorbeeld een “Minute”-kolom) als ik er vaak op wil groeperen, omdat het de groeperingscode minder uitgebreid maakt.

Of je zou iets als dit kunnen proberen:

df.groupby([df['Source'],pd.TimeGrouper(freq='Min')])

Antwoord 2, autoriteit 35%

Aangezien het oorspronkelijke antwoord nogal oud is en panda’s perioden
een andere oplossing is tegenwoordig:

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

Bovendien kunt u hersamplen

df.resample('T')

Antwoord 3, autoriteit 20%

pd.TimeGrouper wordt nu afgeschreven. Hier is v1.05-update met behulp van pd.Grouper

df['Date'] = df.index
df.groupby(['Source',pd.Grouper(key = 'Date', freq='30min')])

Other episodes