2016-12-26 7 views
5

Ich habe folgenden Datenrahmen:Pandas - Aggregat, sortieren und nlargest innerhalb groupby

     some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011 

Und ich brauche wie zu verwandeln, etwas zu tun (‚Größe‘) mit folgenden Art und N max Werte erhalten. Um etwas wie diese zu erhalten (N = 2):

   some_id size 
2016-12-26  001  3 
       008  1 
2016-12-27  009  2 
       003  1 

Gibt es elegante Weise in Pandas 0.19.x zu tun?

Antwort

4

Verwenden Sie value_counts, um verschiedene Zählungen nach der Gruppierung am date Teil Ihrer DateTimeIndex zu berechnen. Dadurch werden sie standardmäßig in absteigender Reihenfolge sortiert.

Sie müssen nur die obersten 2 Zeilen dieses Ergebnisses nehmen, um den größten Teil (top-2) zu erhalten.

fnc = lambda x: x.value_counts().head(2) 
grp = df.groupby(df.index.date)['some_id'].apply(fnc).reset_index(1, name='size') 
grp.rename(columns={'level_1':'some_id'}) 

enter image description here

+0

Es war meine erste Idee, aber ich kann 'head' oder' nlargest' nach value_counts nicht anwenden. –

+0

* Siehe bearbeitet Post * –

+1

Sieht gut aus. Ich denke, wir können den Index nicht zurücksetzen. Nur 'df.groupby (df.index.date) ['some_id']. Anwenden (Lambda x: x.value_counts(). Kopf (2))' –

0

Wenn Sie bereits die sizes Spalte haben, können Sie die folgenden.

df.groupby('some_id')['size'].value_counts().groupby(level=0).nlargest(2) 

Andernfalls könnten Sie diesen Ansatz verwenden.

import pandas as pd 

df = pd.DataFrame({'some_id':[1,1,1,8,9,9,3,11], 
        'some_idx':[26,26,26,26,27,27,27,27]}) 

sizes = df.groupby(['some_id', 'some_idx']).size() 

sizes.groupby(level='some_idx').nlargest(2) 

# some_idx some_id some_idx 
# 26  1  26   3 
#   8  26   1 
# 27  9  27   2 
#   3  27   1 
+0

Ich denke, es ist sehr nah, aber ich habe keine Spalte "Größe" und muss es berechnen. –

+0

Ah, hab ich. Bearbeitet, um diese Anforderung zu berücksichtigen. Ich denke, das Erstellen eines neuen "groupby" -Objekts ist am verständlichsten. – 3novak

2

Setup

from io import StringIO 
import pandas as pd 

txt = """     some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011""" 

df = pd.read_csv(StringIO(txt), sep='\s{2,}', engine='python') 

df.index = pd.to_datetime(df.index) 
df.some_id = df.some_id.astype(str).str.zfill(3) 

df 

        some_id 
2016-12-26 11:03:10  001 
2016-12-26 11:03:13  001 
2016-12-26 12:03:13  001 
2016-12-26 12:03:13  008 
2016-12-27 11:03:10  009 
2016-12-27 11:03:13  009 
2016-12-27 12:03:13  003 
2016-12-27 12:03:13  011 

Verwendung nlargest

df.groupby(pd.TimeGrouper('D')).some_id.value_counts() \ 
    .groupby(level=0, group_keys=False).nlargest(2) 

      some_id 
2016-12-26 001  3 
      008  1 
2016-12-27 009  2 
      003  1 
Name: some_id, dtype: int64 
2

Sie sollten dies in einer Zeile tun können.

df.resample('D')['some_id'].apply(lambda s: s.value_counts().iloc[:2]) 
Verwandte Themen