删除 pandas 中的列的内存有效方法?

Mau*_*cio 6 python dataframe pandas

在 pandas 中删除列而不耗尽内存的最佳方法是什么?

我有一个很大的数据集,经过一些变量操作后,我需要删除大约一半的变量。我尝试使用df.drop(vars, axis=1, inplace=True)但发现我的内存使用量猛增了很多。没有inplace参数也一样。

这是这个旧的 pandas 问题线程中讨论的确切主题,但它已关闭而没有给出答案。关于 SO 有很多类似的问题,但我还没有找到答案,具体是如何在从大数据框中删除许多变量时避免大量内存增加。谢谢!

Giu*_*ano 2

正如@Kraigolas提到的问题中已经建议的那样,出于各种原因不建议就地使用,在这种情况下它甚至不会带来好处。

一般来说,如果数据帧没有以尽可能最优化的形式进行预处理,则删除操作在内存使用方面可能会很繁重。

强制转换数据类型

例如,您可能决定将所有列转换为确切的数据类型以节省空间(请参阅pandas.DataFrame.dtypespandas.DataFrame.astype

使用 python 3.9、pandas 1.4.3 和 numpy 1.23.1 以及tracemalloc的示例:

import pandas as pd
import numpy as np
import tracemalloc

df = pd.DataFrame(data=np.ones((10000,10000)))

tracemalloc.start()

df.drop(df.columns[0:1000], axis=1)

print(f"MB peak of RAM: {tracemalloc.get_traced_memory()[1] / 1024 / 1024}")

tracemalloc.stop()
Run Code Online (Sandbox Code Playgroud)

输出将为687.13 MB

现在,如果将 dtypes 转换为 int 而不是默认的 float64 (在预处理步骤之后明显移动tracemalloc的开始,否则峰值会受到转换的影响),这样:

df = pd.DataFrame(data=np.ones((10000,10000)))
df = df.astype('int8')

tracemalloc.start()

df.drop(df.columns[0:1000], axis=1)

print(f"MB peak of RAM: {tracemalloc.get_traced_memory()[1] / 1024 / 1024}")

tracemalloc.stop()
Run Code Online (Sandbox Code Playgroud)

输出将为86.31MB

使用“iloc”(如果可能)

如果可以通过索引列表定位列(例如,根据某些标准使用pandas.DataFrame.sort_values对它们重新排序),则pandas.DataFrame.iloc的操作将更加高效和快速。

与之前的示例相比,使用 int8 进行 dtype 转换:

tracemalloc.start()

df.iloc[:, 1000:]

print(f"MB peak of RAM: {tracemalloc.get_traced_memory()[1] / 1024 / 1024}")

tracemalloc.stop()
Run Code Online (Sandbox Code Playgroud)

仅使用 0.023 MB RAM


一般来说,向量运算总是比那些使用简单但内部过程耗时的函数性能更高(甚至高出几个数量级),尤其是在 pandas 中。