我使用内存使用量较高的大数据帧,并且我读到,如果更改重复值列上的数据类型,我可以节省大量内存。
我尝试了一下,确实内存使用量下降了 25%,但随后我遇到了我无法理解的性能缓慢问题。
我对 dtype“类别”列进行分组聚合,在更改 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
我试图了解这种缓慢的原因是什么以及是否有办法克服它。
Thanks!
我不确定这种速度下降的原因,但一种解决方法是直接存储类别代码:
df3 = df.copy()
animals = pd.Categorical(df['animals'])
df3['animals'] = animals.codes
df3.groupby('days').agg({'animals': 'first'}).apply(lambda code: animals.categories[code])
它不是最干净的解决方案,因为它需要外部元数据,但它实现了您正在寻找的内存效率和计算速度。深入研究 Pandas 内部所做的事情导致分类速度减慢会很有趣。
编辑:我追查了为什么会发生这种情况......作为first()
聚合,熊猫calls np.asarray()在柱子上 https://github.com/pandas-dev/pandas/blob/0.22.x/pandas/core/groupby.py#L1258-L1271。对于分类列,这最终会将列转换回非分类列,从而导致不必要的开销。解决这个问题将是对 pandas 包的有用贡献!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)