【问题标题】:How can I reduce the memory of a pandas DataFrame?如何减少 pandas DataFrame 的内存?
【发布时间】:2019-08-16 21:34:22
【问题描述】:

我在日常工作中使用 pandas,并且我使用的一些数据框非常大(大约数亿行乘数百列)。有什么方法可以减少 RAM 内存消耗?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以使用此功能。它通过将数据类型限制在每列所需的最小值来减少数据的大小。

    代码不是我的,我从以下链接复制了它,并根据我的需要对其进行了调整。 https://www.mikulskibartosz.name/how-to-reduce-memory-usage-in-pandas/

    def reduce_mem_usage(df, int_cast=True, obj_to_category=False, subset=None):
        """
        Iterate through all the columns of a dataframe and modify the data type to reduce memory usage.
        :param df: dataframe to reduce (pd.DataFrame)
        :param int_cast: indicate if columns should be tried to be casted to int (bool)
        :param obj_to_category: convert non-datetime related objects to category dtype (bool)
        :param subset: subset of columns to analyse (list)
        :return: dataset with the column dtypes adjusted (pd.DataFrame)
        """
        start_mem = df.memory_usage().sum() / 1024 ** 2;
        gc.collect()
        print('Memory usage of dataframe is {:.2f} MB'.format(start_mem))
    
        cols = subset if subset is not None else df.columns.tolist()
    
        for col in tqdm(cols):
            col_type = df[col].dtype
    
            if col_type != object and col_type.name != 'category' and 'datetime' not in col_type.name:
                c_min = df[col].min()
                c_max = df[col].max()
    
                # test if column can be converted to an integer
                treat_as_int = str(col_type)[:3] == 'int'
                if int_cast and not treat_as_int:
                    treat_as_int = check_if_integer(df[col])
    
                if treat_as_int:
                    if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                        df[col] = df[col].astype(np.int8)
                    elif c_min > np.iinfo(np.uint8).min and c_max < np.iinfo(np.uint8).max:
                        df[col] = df[col].astype(np.uint8)
                    elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                        df[col] = df[col].astype(np.int16)
                    elif c_min > np.iinfo(np.uint16).min and c_max < np.iinfo(np.uint16).max:
                        df[col] = df[col].astype(np.uint16)
                    elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                        df[col] = df[col].astype(np.int32)
                    elif c_min > np.iinfo(np.uint32).min and c_max < np.iinfo(np.uint32).max:
                        df[col] = df[col].astype(np.uint32)
                    elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                        df[col] = df[col].astype(np.int64)
                    elif c_min > np.iinfo(np.uint64).min and c_max < np.iinfo(np.uint64).max:
                        df[col] = df[col].astype(np.uint64)
                else:
                    if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                        df[col] = df[col].astype(np.float16)
                    elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                        df[col] = df[col].astype(np.float32)
                    else:
                        df[col] = df[col].astype(np.float64)
            elif 'datetime' not in col_type.name and obj_to_category:
                df[col] = df[col].astype('category')
        gc.collect()
        end_mem = df.memory_usage().sum() / 1024 ** 2
        print('Memory usage after optimization is: {:.3f} MB'.format(end_mem))
        print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
    
        return df
    

    【讨论】:

    • 这段代码缺少导入(gc,tqdm)和“check_if_integer”的定义,甚至更多。
    • 这也是固有缺陷,它完全忽略了可能(并且可能)需要的浮点精度。
    【解决方案2】:

    如果您的数据不适合内存,请考虑使用Dask DataFrames。它具有延迟计算和并行性等不错的功能,允许您将数据保存在磁盘上,并仅在需要结果时以分块方式提取数据。它还具有类似 pandas 的界面,因此您几乎可以保留当前代码。

    【讨论】:

    • 一般来说效果好吗?我像 2 年前一样尝试过,但它非常有问题
    • 对我来说效果很好。但我经常在这里docs.dask.org/en/latest/dataframe-best-practices.html 遵循“减少,然后使用 Pandas”的建议,所以对于更复杂的分析部分,我可能会默认使用 pandas 本身。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2023-02-02
    • 2021-07-21
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    相关资源
    最近更新 更多