【问题标题】:Reducing pandas DataFrame memory consumption by use of scaled data for each column?通过使用每列的缩放数据来减少 pandas DataFrame 内存消耗?
【发布时间】:2020-04-01 08:28:05
【问题描述】:

我想在管理一些 pandas DataFrame 时减少内存消耗。 例如,我知道从 float64 切换到 flot32 的技巧,这很有趣。

更进一步,并且知道我的数值实际上具有“小”的绝对最小值和最大值,我想知道是否不能要求 pandas 对给定列使用比例因子?

最好的例子是百分比。

通过百分比,您知道最小值为 0,最大值为 1。这些最小值和最大值可以存储为列的属性。

然后我可以使用 int16 为例,列值将存储为 [-128; 之间的缩放值; 127]。然后在使用时,它们将使用已存储为列属性的最小值和最大值缩小到它们的“原始值”(进行一些舍入)。

这种方法可以用于管理 pandas DataFrames 吗?

感谢您的帮助和反馈! 最好的,

【问题讨论】:

    标签: python pandas memory-management


    【解决方案1】:

    我使用这个有用的辅助函数。但当然可以使用更好的解决方案。

    def reduce_mem_usage(data_frame):
        start_mem_usg = data_frame.memory_usage(deep=True).sum() / 1024 ** 2
        print("Memory usage of the dataframe is : {:03.2f} {}".format(start_mem_usg, " MB"))
        for col in data_frame.columns:
            if data_frame[col].dtype not in [object, "datetime64", "datetime64[ns]"]:  # Exclude strings
    
                print("******************************")
                print("Column: ", col)
                print("dtype before: ", data_frame[col].dtype)
                is_int = False
                try:
                    mx = data_frame[col].max()
                except Exception:
                    continue
                mn = data_frame[col].min()
                try:
                    as_int = data_frame[col].fillna(0).astype(numpy.int64)
                    result = (data_frame[col] - as_int)
                    result = result.sum()
                    if result > -0.01 and result < 0.01:
                        is_int = True
                except:
                    continue
    
                try:
    
                    if is_int:
                        if mn >= 0:
                            if mx < 255:
                                data_frame[col] = data_frame[col].astype(numpy.uint8)
                            elif mx < 65535:
                                data_frame[col] = data_frame[col].astype(numpy.uint16)
                            elif mx < 4294967295:
                                data_frame[col] = data_frame[col].astype(numpy.uint32)
                            else:
                                data_frame[col] = data_frame[col].astype(numpy.uint64)
                        else:
                            if mn > numpy.iinfo(numpy.int8).min and mx < numpy.iinfo(numpy.int8).max:
                                data_frame[col] = data_frame[col].astype(numpy.int8)
                            elif mn > numpy.iinfo(numpy.int16).min and mx < numpy.iinfo(numpy.int16).max:
                                data_frame[col] = data_frame[col].astype(numpy.int16)
                            elif mn > numpy.iinfo(numpy.int32).min and mx < numpy.iinfo(numpy.int32).max:
                                data_frame[col] = data_frame[col].astype(numpy.int32)
                            elif mn > numpy.iinfo(numpy.int64).min and mx < numpy.iinfo(numpy.int64).max:
                                data_frame[col] = data_frame[col].astype(numpy.int64)
    
                                # Make float datatypes 32 bit
                    else:
                        data_frame[col] = data_frame[col].astype(numpy.float32)
                    print("dtype after: ", data_frame[col].dtype)
                    print("******************************")
                except ValueError:
                    continue
        print("___MEMORY USAGE AFTER COMPLETION:___")
        mem_usg = data_frame.memory_usage(deep=True).sum() / 1024 ** 2
        print("Memory usage is: {:03.2f} {}".format(mem_usg, " MB"))
        print("This is ", 100 * mem_usg / start_mem_usg, "% of the initial size")
        return data_frame
    

    【讨论】:

    • 你知道这个函数是谁写的吗?它是 DataScience 社区中广泛使用的功能。
    • 对不起,我不知道。社区里很多人都在网上发表过,所以我真的不知道第一个人。
    • @mustafasencer 谢谢,我会看看。我发现这并不完全是我的想法,因为它不做缩放,但它可以是一个非常好的起点。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 2016-07-20
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多