您的位置:首页 > 娱乐 > 明星 > 北京软件开发工程师_怎么样做小程序_seo职位_互联网全媒体广告代理

北京软件开发工程师_怎么样做小程序_seo职位_互联网全媒体广告代理

2024/12/23 10:25:26 来源:https://blog.csdn.net/dydyswr/article/details/144520264  浏览:    关键词:北京软件开发工程师_怎么样做小程序_seo职位_互联网全媒体广告代理
北京软件开发工程师_怎么样做小程序_seo职位_互联网全媒体广告代理

        最近我用python处理excel,使用的是pandas库,我发现pandas库非常占用内存,一直想研究下如何优化pandas的内存占用,但一直没腾出空来,最近终于有时间研究一把了,我先把优化方法写上,如果你想了解更多的内容,可以看一下XX这篇文章,我优化的思路来源https://www.sohu.com/a/484114754_121124370这篇文章。

        以下直接提供了优化方法,如果你想知道为什么这么做,可以参考我的另一篇文章链接: python pandas 优化内存占用(二)

1.优化结果

1.1 优化前

        我优化的是一个20万行,88列的excel文件,源文件有76.59M,因为业务敏感性的原因,源文件我不能贴出来。
        先看一下优化之前excel占用了多少内存

# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 200000 entries, 0 to 199999
# Data columns (total 88 columns):
#  #   Column           Non-Null Count   Dtype
# ---  ------           --------------   -----
#  0   column0          200000 non-null  int64
#  1   column1        200000 non-null  object
#  2   column2          200000 non-null  int64
......
#  85  column85            199963 non-null  float64
#  86  column86            199963 non-null  object
#  87  column87         199963 non-null  float64
# dtypes: float64(14), int64(3), object(71)
# memory usage: 965.9 MB

        上面的输出我精简了一下,从上边的输出可以看出,我的excel文件有200000行,88列,其中有14个float64类型的列,3个int64类型的列,71个ojbect类型的列,总共占用内存965.9M。

        上面的输出是使用如下的代码得到的。

gl.info(memory_usage='deep')

1.2 优化后

# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 200000 entries, 0 to 199999
# Data columns (total 88 columns):
#  #   Column           Non-Null Count   Dtype
# ---  ------           --------------   -----
#  0   column0          200000 non-null  uint64
#  1   column1        200000 non-null  object
#  2   column2          200000 non-null  uint64
......
#  84  是否小区             199963 non-null  category
#  85  column85            199963 non-null  category
#  86  column86            199963 non-null  category
#  87  column87         199963 non-null  category
# dtypes: category(81), object(5), uint64(2)
# memory usage: 143.8 MB

        同样,我把优化后的输出也精简了一下,从上边的输出可以看出,我这个200000行,88列的excel文件优化后占用内存143.8M,优化效果还是非常明显的。
        细心的小伙伴可能注意到一个问题,优化后,我的execl文件的列类型变化了,优化前有14个float64类型的列,3个int64类型的列,71个ojbect类型的列;优化后变成了81个category类型的列,5个object类型列,2个uint64类型的列。没错,正如你看到的,这就是优化的秘密,为什么这样可以优化内存使用,可以参看我的另一篇文章,下面我讲一下我是如何做到的。

2. 优化方法

        正如小伙伴在上文中看到的,要想优化excel的内存占用大小,一个重要的思路是改变excel的列类型,如何获取优化后的列类型呢,代码如下

import pandas as pd
# 把excel中的数据类型转化成优化后的数据类型
def convert_to_right_type():# 读取文件gl = pd.read_excel("xx.xlsx")# 初始化一个DataFrameconverted_obj = pd.DataFrame()# 计算哪些列类型可以转换成category类型for col in gl.columns:num_unique_values = len(gl[col].unique())num_total_values = len(gl[col])if num_unique_values / num_total_values < 0.5:converted_obj.loc[:, col] = gl[col].astype('category')else:converted_obj.loc[:, col] = gl[col]# 计算哪些int类型列可以downcast成子类型gl_int = converted_obj.select_dtypes(include=['int'])converted_int = gl_int.apply(pd.to_numeric, downcast='unsigned')# 将转换后的int类型列合并回converted_objfor col in converted_int.columns:converted_obj[col] = converted_int[col]# 计算哪些float类型列可以downcast成子类型gl_float = converted_obj.select_dtypes(include=['float'])converted_float = gl_float.apply(pd.to_numeric, downcast='float')# 将转换后的 float 类型列合并回converted_objfor col in converted_float.columns:converted_obj[col] = converted_float[col]# 获取数据类型索引(索引是列名,值是数据类型)dtypes = converted_obj.dtypes# 获取列名dtypes_col = dtypes.index# 获取数据类型的名称dtypes_type = [i.name for i in dtypes.values]# 列名和类型字典column_types = dict(zip(dtypes_col, dtypes_type))# preview = {key: value for key, value in list(column_types.items())[:20]}# 获取字典preview = {key: value for key, value in list(column_types.items())}# 格式化输出, 使每个嵌套层级的缩进量为4个空格pp = pprint.PrettyPrinter(indent=4)# 打印字典pp.pprint(preview)

        这段儿代码的输出类似如下:

column_types = {'column1': 'category','column2': 'uint64','column3': 'object','column4': 'uint64','column5': 'category'}

        column_type 是个字典,它的key是excel文件的列名称,value是excel文件列对应的优化后的类型。

        在读取excel的时候,指定excel的dtype,即可按照指定的列类型读取excel,类似这样

gl = pd.read_excel("XX.xlsx", dtype=column_types)

3. 测试方法

        我是用如下的代码测试excel占用内存的大小的

# 测试内存占用
def mem_usage(pandas_obj):if isinstance(pandas_obj, pd.DataFrame):usage_b = pandas_obj.memory_usage(deep=True).sum()else:  # we assume if not a df it's a seriesusage_b = pandas_obj.memory_usage(deep=True)usage_mb = usage_b / 1024 ** 2  # convert bytes to megabytesreturn "{:03.2f} MB".format(usage_mb)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com