将大型 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
我需要将此数据帧转换为密集的 int
s 以进行进一步处理(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')
我正在从具有大量列(~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
我需要将此数据帧转换为密集的 int
s 以进行进一步处理(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')