2017-12-01 1 views
2

Ich habe einen Pandas Datenrahmen data_1 wie folgt benannt:Wie kann man die Geschwindigkeit eines aggregierten Vorgangs auf einem Pandas-Dataframe verbessern?

tenant_id tenant_class_id tenant_date 
100   10001   2004-01-10 
100   10001   2004-08-25 
101   10001   2016-09-20 
102   10002   2013-07-12 
103   10003   2011-04-05 
103   10004   2002-05-05 
103   10003   2003-12-26 

Mein Ziel ist es, die früheste/erste tenant_date für jeden tenant_id zu finden. Die tenant_id ist in long Format und tenant_date ist in datetime64 Format

ich diesen Code verwenden es für die Berechnung:

output = data_1.groupby(['tenant_id']).apply(lambda x: x.nsmallest(1, 'tenant_date')).reset_index(drop=1) 

Diese für kleinere Datensätze perfekt funktioniert gut, aber meine data_1 enthält etwa 200 Millionen Zeilen. Dieser Code wird nie vervollständigt. Ich habe genug Speicher mit etwa 244 GB RAM. Gibt es eine effizientere Möglichkeit, dies schnell zu tun?

Antwort

2

Sortieren dann verwenden Sie drop_duplicates. Stellen Sie jedoch sicher, dass die Datumsspalte zuerst in Datetime geändert wird.

df['tenant_date'] = pd.to_datetime(df['tenant_date']) 
df.sort_values(['tenant_id', 'tenant_date']).drop_duplicates('tenant_id') 

    tenant_id tenant_class_id tenant_date 
0  100   10001 2004-01-10 
2  101   10001 2016-09-20 
3  102   10002 2013-07-12 
5  103   10004 2002-05-05 
2

können Sie versuchen, sort_values + drop_duplicates:

output = data_1.sort_values(['tenant_id','tenant_date']).drop_duplicates(['tenant_id']) 

Oder sort_values + GroupBy.head:

output = data_1.sort_values(['tenant_id','tenant_date']).groupby(['tenant_id']).head(1) 

Oder seelct min Indizes pro Gruppen von idxmin:

output = data_1.loc[data_1.groupby(['tenant_id'])['tenant_date'].idxmin()] 

Oder:

output = data_1.set_index(['tenant_class_id']) 
       .groupby(['tenant_id'])['tenant_date'].nsmallest(1).reset_index() 

Timings:

np.random.seed(123) 
N = 1000000 
L = pd.date_range('2015-01-01', '2018-01-01') 

df = pd.DataFrame({'tenant_date': np.random.choice(L, size=N), 
        'tenant_id':np.random.randint(1000,size=N), 
        'tenant_class_id':np.random.randint(1000,size=N)}) 
print (df) 

In [99]: %timeit data_1.sort_values(['tenant_id','tenant_date']).drop_duplicates(['tenant_id']) 
1000 loops, best of 3: 1.97 ms per loop 

In [100]: %timeit data_1.sort_values(['tenant_id','tenant_date']).groupby(['tenant_id']).head(1) 
1000 loops, best of 3: 2.07 ms per loop 

In [101]: %timeit data_1.loc[data_1.groupby(['tenant_id'])['tenant_date'].idxmin()] 
100 loops, best of 3: 2.04 ms per loop 

In [102]: %timeit data_1.set_index(['tenant_class_id']).groupby(['tenant_id'])['tenant_date'].nsmallest(1).reset_index() 
100 loops, best of 3: 8.64 ms per loop 

In [103]: %timeit data_1.groupby(['tenant_id']).apply(lambda x: x.nsmallest(1, 'tenant_date')).reset_index(drop=1) 
100 loops, best of 3: 11.4 ms per loop 

Caveat

Die Ergebnisse nicht Leistung adressieren die Anzahl der Gruppen gegeben, die Timings viel für einige dieser Lösungen auswirken wird.

Verwandte Themen