2017-12-31 162 views
3

メモリ使用量の多い大きなデータフレームで作業しています。繰り返し値列のdtypeを変更すると、大量のメモリを節約できます。Pandas DataFrame - dtype == 'category'の列が集計されているとパフォーマンスが低下する

私はそれを試してみましたが、実際にはメモリの使用量を25%削減しましたが、その後は理解できないパフォーマンスの低下にぶつかりました。

dtypeの 'category'カラムでgroup-by aggregationを行い、dtypeを変更する前に約1秒かかり、変更後に約1分かかりました。

このコードは、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 

私が理解しようとすると、この遅さの原因が何であるかであり、それを克服する方法があるかどうか。

ありがとうございます!

答えて

3

私はこの減速がどこから来ているかどうか分からない、が、1つの回避策は、直接、カテゴリコードを格納することです:

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

それはきれいな解決策ではありません、それは外部のメタデータを必要とするため、それが両方の実現しますメモリ効率と計算速度が向上します。パンダスが内部的にやっていることを掘り下げて、このカテゴリーの減速を引き起こすのは面白いだろう。


編集:これはなぜ起こるか... first()集約、パンダcalls np.asarray() on the columnの一環として、私がダウンして追跡しました。カテゴリの列の場合、これは列を非カテゴリに戻すことになり、不要なオーバーヘッドにつながります。これを修正すると、パンダのパッケージに役立ちます!

関連する問題