我正在使用约 70 GB 的数据帧,其中包含约 700 万行和 56 列。我想将此数据帧子集化为较小的数据帧,从原始数据帧中取出 100.000 个随机行。
在这样做时,我观察到了非常奇怪的行为:
df
是我的 700 万行数据帧,我将其作为 .parquet 文件读入 python。
我首先尝试了以下方法:
import pandas as pd
df = df.sample(100000)
但是,执行这个块需要很长时间。我总是在十分钟后中断命令,因为我确信从数据框中绘制随机行不会花那么长时间
现在,如果我执行以下块,代码将在几秒钟内运行完毕:
import pandas as pd
df2 = df
df = df2.sample(100000)
那里发生了什么?为什么 .sample() 在第一次尝试中花费很长时间,而在第二次尝试中只需要几秒钟就执行?复制数据帧如何影响计算速度?
df
和df2
应该是完全相同的物体吧?我当然现在可以继续使用 df2,但我不希望在内存中存储两个 70 GB 的文件。
这就是我相信正在发生的事情。
在这段代码中
import pandas as pd
df = df.sample(100000)
原始数据帧的引用计数降至零,并且被垃圾收集。一旦数据帧被垃圾收集,您的数据帧包含的任何 python 对象(除了您采样的 100k 之外)也会被垃圾收集。
在这段代码中
import pandas as pd
df2 = df
df = df2.sample(100000)
将样本分配给
df
后,原始数据帧仍由名称 df2
引用,因此不会被垃圾收集。
验证这一点的方法是将你的第二个版本更改为
import pandas as pd
df2 = df
df = df2.sample(100000)
del df2
执行
del df2
将删除名称 df2
导致引用计数降至零。您应该会看到此版本与您的原始代码一样长。