前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据类型合理选择有效减少内存占用

数据类型合理选择有效减少内存占用

作者头像
用户8949263
发布2022-11-07 12:55:36
1.6K0
发布2022-11-07 12:55:36
举报
文章被收录于专栏:Python数据分析实例

如何优化大数据集内存占用?在用Pandas进行数据分析时,首先对读取的数据清洗操作包括剔除空列、去除不合要求的表头、设置列名等,而经常忽略对数据列设置相应的数据类型,而数据类型设置对大数据集内存占用产生重要影响。

1、优化数据类型减少内存占用

一般来说pandas 它会自动推断出数据类型,如果数值型列数据包括了缺失值,推断数据类型就会自动填充为浮点型。推断的数据类型并不一定是最优,有时候会产生意想不到的结果。

通常情况下,Pandas对读取的数据列默认是设置为object数据类型,这种通用类型因自身的兼容性会导致所读取的数据占据较大的内存空间,倘若能给它们设置合适的数据类型,就可以降低该数据集的实际内存占用,从而提升运行效率。

pandas、python 和 numpy 之间类型总结

Pandas dtype

Python type

NumPy type

Usage

object

str or mixed

string_, unicode_, mixed types

Text or mixed numeric and non-numeric values

int64

int

int_, int8, int16, int32, int64, uint8, uint16, uint32, uint64

Integer numbers

float64

float

float_, float16, float32, float64

Floating point numbers

bool

bool

bool_

True/False values

datetime64

NA

datetime64[ns]

Date and time values

timedelta[ns]

NA

NA

Differences between two datetimes

category

NA

NA

Finite list of text values

测试数据集:Index of /ml/machine-learning-databases/00616 (uci.edu)

首先看一下数据集的各列分别是什么数据类型:

代码语言:javascript
复制

import pandas as pd
df = pd.read_csv('Tetuan City power consumption.csv')
print(df.dtypes)

从上图可以看出,数据类型分别为object和int64两种,从数据的显示情况来看,DateTime列可以设置为日期类型,重新设置对比如下:

代码语言:javascript
复制

import pandas as pd
df1 =df.copy()
print(df1.head())
df1['DateTime'] = pd.to_datetime(df1['DateTime'])
print(df1.dtypes)

利用DataFrame的memory_usage属性对内存测量,需要为memory_usage添加deep=True:

代码语言:javascript
复制
df.memory_usage(deep=True)

对比df和df1数据集内存使用量进行求和,并设置为以Mb为单位:

代码语言:javascript
复制
print(f"{df.memory_usage(deep=True).sum()/1024**2:.2f}Mb")
print(f"{df1.memory_usage(deep=True).sum()/1024**2:.2f}Mb")

从上图可以看出,通过对数据列的数据类型设置,其内存有了明显下降,然而我们还可以继续进行设置,因为Pandas中的浮点类型有float16、float32、float64三类,它们对应不同的小数范围:

代码语言:javascript
复制
import numpy as np
print(f"{np.finfo(np.float16).min}~{np.finfo(np.float16).max}")
print(f"{np.finfo(np.float32).min}~{np.finfo(np.float32).max}")
print(f"{np.finfo(np.float64).min}~{np.finfo(np.float64).max}")

数据集小数默认均是floa64,那么究竟应该是哪种浮点型类型合适呢,我们来看一下各列最小~最大值范围:

代码语言:javascript
复制
df.describe()

从结果来看,我们可以将各列均设置为float16即可满足:

代码语言:javascript
复制
df1['Temperature'] = df1['Temperature'].astype(np.float16)
df1['Humidity'] = df1['Humidity'].astype(np.float16)
df1['Wind Speed'] = df1['Wind Speed'].astype(np.float16)
df1['general diffuse flows'] = df1['general diffuse flows'].astype(np.float16)
df1['diffuse flows'] = df1['diffuse flows'].astype(np.float16)
df1['general diffuse flows'] = df1['general diffuse flows'].astype(np.float16)
df1['Zone 1 Power Consumption'] = df1['Zone 1 Power Consumption'].astype(np.float16)
df1['Zone 2  Power Consumption'] = df1['Zone 2  Power Consumption'].astype(np.float16)
df1['Zone 3  Power Consumption'] = df1['Zone 3  Power Consumption'].astype(np.float16)
print(df1.dtypes)

最后看一下df1的内存使用大小:

代码语言:javascript
复制
print(f"{df1.memory_usage(deep=True).sum()/1024**2:.2f}Mb")
1.20Mb

内存占用从3.6Mb减小到了1.2Mb,数据类型优化设置确实有效降低内存使用。

当字段多手动确实麻烦,自动设置数据集的合理数据类型。

思路:遍历每一列,然后找出该列的最大值与最小值,我们将这些最大最小值与子类型当中的最大最小值去做比较,选择字节数最小的子类型。

代码如下:

代码语言:javascript
复制
def reset_datatype(df):
    def _reset_datatype(x):
        unique_data = list(x.unique())
        try:
            unique_data.remove(np.nan)
        except:
            pass
        cat_ratio = len(unique_data) / len(x)

        if 'int' in x.dtype.name:
            c_min = x.min()
            c_max = x.max()

            if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                x = x.astype(np.int8)
            elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                x = x.astype(np.int16)
            elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                x = x.astype(np.int32)
            elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                x = x.astype(np.int64)

        elif 'float' in x.dtype.name:
            c_min = x.min()
            c_max = x.max()
            if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                x = x.astype(np.float16)
            elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                x = x.astype(np.float32)
            else:
                x = x.astype(np.float64)

        else:
            try:
                x = pd.to_datetime(x)
            except:
                if all(str(i).lower() in ['true', 'false'] for i in unique_data):
                    x = x.astype('boolean')
                elif cat_ratio < 0.1:
                    x = x.astype('category')
                elif all(isinstance(i, str) for i in unique_data):
                    x = x.astype('string')

        return x

    return df.apply(lambda x: _reset_datatype(x))

2、数据分块

read_csv()方法当中的chunksize参数

read_csv()方法当中的chunksize参数顾名思义就是对于超大csv文件,我们可以分块来进行读取,例如文件当中有7000万行的数据,我们将chunksize参数设置为100万,每次分100万来分批读取。

df_chunk = pd.read_csv(r'data.csv', chunksize=1000000)

df_chunk并非是一个DataFrame对象,而是一个可迭代的对象。

小结

本文对于Pandas读取csv后的数据占用内存问题进行了分析,并给出了通过对数据类型合理设置来减小大数据集内存占用。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python数据分析实例 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2、数据分块
  • read_csv()方法当中的chunksize参数
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档