.dropna()会增加内存使用量

4

首先我导入整个文件,并获得了1002.0+ KB的内存消耗。

df = pd.read_csv(
    filepath_or_buffer="./dataset/chicago.csv"
)
print(df.info())

# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 32063 entries, 0 to 32062
# Data columns (total 4 columns):
# Name                      32062 non-null object
# Position Title            32062 non-null object
# Department                32062 non-null object
# Employee Annual Salary    32062 non-null object
# dtypes: object(4)
# memory usage: 1002.0+ KB
# None

然后我删除NaN,再次运行脚本,内存消耗为1.2+ MB。
df = pd.read_csv(
    filepath_or_buffer="./dataset/chicago.csv"
).dropna(how="all")

# <class 'pandas.core.frame.DataFrame'>
# Int64Index: 32062 entries, 0 to 32061
# Data columns (total 4 columns):
# Name                      32062 non-null object
# Position Title            32062 non-null object
# Department                32062 non-null object
# Employee Annual Salary    32062 non-null object
# dtypes: object(4)
# memory usage: 1.2+ MB
# None

由于我将一个行删除,我期望内存消耗会降低或至少保持不变,但实际情况并非如此。

有人知道为什么会这样吗?还是该如何解决?或者这是个bug吗?

编辑:chicago.csv


你的索引已经改变了。之前它是一个 RangeIndex,这很好用,因为你只需要开始和结束值。现在由于你删除了一行,你有了一个 Int64Index,它需要更多的内存。尝试在最后添加 .reset_index()(我不确定,但它可能会将索引转换回范围)。 - pault
你只是少删了一行,所以实际上不会有太大的影响。 - lorenzori
2个回答

12

变化是由于你的索引从RangeIndex变为了Int64Index,后者需要更多内存。

你可以在dropna()之后重置索引来“修复”它,但这会带来改变行索引(也许您并不关心)的副作用。

下面是一个说明性的例子:

首先创建一个示例DataFrame:

df = pd.DataFrame({"a": range(10000)})
df.loc[1000, "a"] = None

打印信息:

print(df.info())
#<class 'pandas.core.frame.DataFrame'>
#RangeIndex: 10000 entries, 0 to 9999
#Data columns (total 1 columns):
#a    9999 non-null float64
#dtypes: float64(1)
#memory usage: 78.2 KB

删除缺失值:

print(df.dropna().info())
#<class 'pandas.core.frame.DataFrame'>
#Int64Index: 9999 entries, 0 to 9999
#Data columns (total 1 columns):
#a    9999 non-null float64
#dtypes: float64(1)
#memory usage: 156.2 KB

重置(和删除)索引:

df.dropna().reset_index(drop=True).info()
#<class 'pandas.core.frame.DataFrame'>
#RangeIndex: 9999 entries, 0 to 9998
#Data columns (total 1 columns):
#a    9999 non-null float64
#dtypes: float64(1)
#memory usage: 78.2 KB

1
这是一个非常有见地的答案! - sophros
1
很棒的回答和优秀的信息。谢谢@pault。我在这里学到了一些东西。+1 - Scott Boston
感谢您的回答@pault,但是如果我关心索引怎么办?假设我有:df = pd.read_csv( filepath_or_buffer="./dataset/chicago.csv", index_col="Name" ) - juanp_1982
@juanp_1982 还是RangeIndex吗?在这种情况下,您仍然看到内存增加吗?能否编辑您的问题以提供[mcve]? - pault
@pault:我之前没有测试过(我以为我已经测试过了)。我刚刚再次运行了我的脚本,并使用了index_col,它的表现符合我的预期,内存消耗降低了。我刚刚学到了在数据框中设置索引的另一个原因,而且我不需要使用.reset_index()。 - juanp_1982

-2

这不是一个 bug。它按照预期工作,因为您正在加载文件,所以它占用了与之前相同的内存量,但由于您随后搜索数据框并删除具有 NaN 的行,这增加了内存使用量。


你能详细解释一下吗?我不明白为什么“删除具有NaN的行会增加内存使用量。” - juanp_1982
因为您首先加载所有数据,然后再删除行。它们不是同时完成的。 - D.Sanders

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接