2017-12-31 98 views
3

Ich arbeite mit großen Datenrahmen mit hoher Speicherauslastung und ich lese, dass, wenn ich den dtype auf wiederholte Werte Spalten ändern kann ich viel Speicher sparen.Pandas DataFrame - Aggregat auf Spalte whos dtype == 'Kategorie' führt zu langsamer Leistung

Ich habe es versucht und in der Tat sank die Speicherauslastung um 25%, aber dann stieß ich auf eine Performance-Langsamkeit, die ich nicht verstehen konnte.

Ich mache Group-by-Aggregation auf die dtype 'Kategorie' Spalten und bevor ich den dtype änderte dauerte es etwa 1 Sekunde und nach der Änderung dauerte es etwa 1 Minute.

Dieser Code zeigt die Leistungsverschlechterung durch den Faktor 2:

import pandas as pd 
import random 

animals = ['Dog', 'Cat'] 
days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday','Saturday'] 

columns_dict = {'animals': [], 
       'days': []} 

for i in range(1000000): 
    columns_dict['animals'].append(animals[random.randint(0, len(animals)-1)]) 
    columns_dict['days'].append(days[random.randint(0, len(days)-1)]) 

# df without 'category' dtype 
df = pd.DataFrame(columns_dict) 

df.info(memory_usage='deep') # will result in memory usage of 95.5 MB 

%timeit -n100 df.groupby('days').agg({'animals': 'first'}) 
# will result in: 100 loops, best of 3: 54.2 ms per loop 

# df with 'category' dtype 
df2 = df.copy() 
df2['animals'] = df2['animals'].astype('category') 

df2.info(memory_usage='deep') # will result in memory usage of 50.7 MB 

%timeit -n100 df2.groupby('days').agg({'animals': 'first'}) 
# will result in: 100 loops, best of 3: 111 ms per loop 

Was ich versuche, ist, was zu verstehen ist, die Ursache für diese Langsamkeit und ob es einen Weg, sie zu überwinden ist.

Danke!

Antwort

3

Ich bin nicht sicher, wo diese Verlangsamung herkommt, aber eine Abhilfe ist, die Kategorie-Codes zu speichern direkt:

df3 = df.copy() 
animals = pd.Categorical(df['animals']) 
df3['animals'] = animals.codes 
df3.groupby('days').agg({'animals': 'first'}).apply(lambda code: animals.categories[code]) 

Es ist nicht die sauberste Lösung, weil es externe Metadaten erfordert, aber es erreicht sowohl die Speichereffizienz und die Rechengeschwindigkeit, nach der Sie suchen. Es wäre interessant zu erfahren, was Pandas intern macht, was diese Verlangsamung für kategorische Dinge verursacht.


Edit: Ich aufgespürt, warum dies passiert ... als Teil der first() Aggregation, Pandas calls np.asarray() on the column. Bei einer kategorialen Spalte wird die Spalte schließlich in nicht kategoriale Werte konvertiert, was zu unnötigem Overhead führt. Dies zu beheben wäre ein nützlicher Beitrag zum Pandas-Paket!

Verwandte Themen