将大型 Pandas 数据帧从 "sparse" 浮点数转换为整数

Converting large Pandas Dataframe from "sparse" float to int

我正在从具有大量列(~20000)的上游组件接收 Pandas DataFrame,它们都有数据类型 float64 并且大多数条目是 NaN(这是 bag of words 编码文档)。示例:

1   2.0 NaN 1.0 NaN NaN NaN 1.0 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3   NaN NaN 1.0 NaN 4.0 NaN 1.0 NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

我需要将此数据帧转换为密集的 ints 以进行进一步处理(int8 在这种情况下就足够了)。我知道在Pandas中,你可以像这样转换和填充缺失值

df.fillna(0).astype(np.int8)

问题是一旦代码开始填充缺失值,它很快就会溢出内存并崩溃。

目前,我将 Dataframe 保存在磁盘上并使用另一个脚本逐行处理它(将浮点数转换为整数并将 NaN 替换为 0),然后由 [=37= 再次读取] 作为 int8 (pd.read_csv("preprocessed.csv", dtype=np.int8)).

结果(包含 int8 个值的数据框)适合内存。

我的问题 - 是否有一些有效的方法可以在 Pandas 中进行此转换(将 float64 转换为 int8,同时将 NaN 替换为 0)而不会溢出内存? (原始数据帧和所需数据帧都适合内存,只是上述 Pandas 代码没有)

分块进行转换,而不是一次性完成

  • 从重型数据帧 A 开始
  • 创建一个新的数据框 B
  • 将范围从 A 复制到新数据帧 C(选择块大小以免超出内存)
  • 将 C 中的范围转换为所需的类型(可以与前面的步骤结合使用)
  • 删除 A 中的旧范围
  • 将 C 加入 A
  • 重复直到所有范围都被转换

您似乎对内存有限制。在这种情况下,尽量不要链式操作。即:

df = df.fillna(0)
df = df.astype('int8')

如果行数少于列数,则在行上使用 apply

df = df.apply(lambda x: x.fillna(0).astype('int8'), axis=1)

但是,由于 csv 文件中的大部分单元格都是空字符串,我认为您最好这样做:

df = pd.read_csv('file.csv', dtype='str')