2017-12-31 38 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

나는이 둔화은 어디에서 오는 확실하지 않다,하지만 한 가지 해결 방법은 직접 분류 코드를 저장하는 것입니다 :

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로 ... 아래로 추적. 범주 형 열의 경우 열이 비 범주 형으로 다시 변환되어 결국 불필요한 오버 헤드가 발생합니다. 이 문제를 해결하면 판다 패키지에 유용하게 기여할 수 있습니다!