为什么Pandas数据框占用的内存比原始文本文件的大小要大得多?

12

我正在尝试使用pandas pd.read_csv("file.txt",sep="\t")将一个大小为3GB的tab/txt文件导入Python。我加载的文件是一个“.tab”文件,我将扩展名更改为“.txt”以便使用read_csv()导入。这是一个具有305列和+/- 1,000,000行的文件。

当我执行代码时,一段时间后Python返回MemoryError。我搜索了一些信息,基本上意味着没有足够的可用RAM。当我在read_csv()中指定nrows = 20时,它可以正常工作。

我使用的计算机有46GB的RAM,其中大约有20GB可供Python使用。

我的问题是:一个大小为3GB的文件需要超过20GB的RAM才能使用pandas read_csv()导入到Python中吗?我做错了什么吗?

编辑:当执行df.dtypes时,类型是objectfloat64int64的混合体

更新:我使用以下代码解决了问题并执行了我的计算:

summed_cols=pd.DataFrame(columns=["sample","read sum"])
while x<352:
    x=x+1
    sample_col=pd.read_csv("file.txt",sep="\t",usecols=[x])
    summed_cols=summed_cols.append(pd.DataFrame({"sample":[sample_col.columns[0]],"read sum":sum(sample_col[sample_col.columns[0]])}))
    del sample_col

现在,它会选择一列数据,在数据框中进行计算,并将结果存储起来,然后删除当前的这一列,继续到下一列。


1
你有检查这个吗?https://dev59.com/-5nga4cB1Zd3GeqPTxtR - PV8
谢谢您提供的链接!在搜索信息时,这个没有弹出来! - Robvh
一个可能的解决方案是分块读取文件。请参见这个其他问题 - AlCorreia
@AlCorreia 我也考虑过那个解决方案,但由于我必须计算整个列的总和,加载行块似乎不是一个好的解决方案。遍历列(请参见我的更新)完美地解决了这个问题。 - Robvh
1个回答

15
Pandas会将文件切割并单独存储数据。我不知道数据类型,所以会假设最坏情况:字符串。
在我的机器上,Python中一个空字符串需要49个字节,如果是ASCII字符(或Unicode则每个字符需要额外1个字节),每行305个空字段大约需要15Kb。150万行这样的数据在内存中大约需要22Gb,在CSV文件中大约需要437Mb。
Pandas/numpy擅长处理数字,因为它们可以非常紧凑地表示数字系列(就像C程序一样)。一旦你离开与C兼容的数据类型,它就会像Python一样使用内存,这样做...不太节省。

这只证明了一个列。检查 df.dtypes。如果其中任何一个是 object,那么该列将存储为 Python 对象。另一种可能性是...你确实需要比你拥有的更多的内存。文件中有多少行? - Amadan
object dtype 表示它被存储为 Python 对象。sys.getsizeof(1) 将告诉你(至少在我的电脑上)Python 用 28 字节的内存表示一个整数。sys.getsizeof("") 将确认我之前关于 Python 字符串的说法。然而,np.float64np.int64 都只使用了 8 个字节(=64 位)。 - Amadan
对我来说,Python 返回以下结果:sys.getsizeof("object") = 31 - sys.getsizeof("float64") = 32 - sys.getsizeof("int64") = 30。这些数字比你的值高得多?这怎么可能呢? - Robvh
啊,这很有道理。谢谢你提供的信息。你有什么建议吗?我正在考虑将文件拆分为列,因为我需要按列进行计算(例如df["col 1"].sum()),而不是在列之间进行计算。 - Robvh
非常感谢您的帮助!非常感激。 - Robvh
显示剩余6条评论

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