Pandas DataFrame 可能有什么问题?
What could be wrong with a Pandas DataFrame?
我无法理解:我有一个函数可以从 S3 存储桶中读取一堆 csv 文件,将它们与 returns DataFrame 连接起来:
def create_df():
df1 = pd.read_csv(s3_path + 'file_1.csv')
df2 = pd.read_csv(s3_path + 'file_2.csv')
return pd.concat([df1, df2], ignore_index=True)
我的第二个函数执行聚合:
def aggregate_values(df):
columns = ['col_c', 'col_d']
new_df = df.groupby(columns, as_index=False) \
.agg({'col_a': 'sum', 'col_b': 'mean'})
return new_df
函数 aggregate_values 由于内存不足错误而失败。
df = create_df()
# OOM error !!!
new_df = aggregate_values(df)
奇怪的是,如果我将 DataFrame 写入我的本地文件系统,然后将其读回,则聚合在新的 DataFrame 上正常工作。
df = create_df()
df.to_csv('path_to_store/f.csv', index=False)
df2 = pd.read_csv('path_to_store/f.csv')
# works fine!!!
new_df = aggregate_values(df2)
我的猜测是 create_df() 返回的 DataFrame 有问题。通过写出来并在 Pandas 中读回以某种方式解决了这个问题。但我想找出 DataFrame 到底出了什么问题。
我该如何调试这个问题?
已编辑
我机器上有32G内存运行代码。 DataFrame 有大约 200 万条记录,占用大约 0.5G 的存储和内存 space.
你没有评论你的内存大小,
也不是 .CSV 或数据框的大小。
但我可以冒险做出一些猜测。
我有几点观察:
- 连接后,您有机会核对 df1 和 df2。只需将
None
分配给它们,即可回收一些 RAM。
- .groupby() 可能接受密集的 numpy 数组并生成 higher-overhead 稀疏数组。你可能想调查一下。
- 计算平均值可能会变成例如
int8
变成 float64
,这显然会消耗更多 space。
- 这是最大的项目:.groupby() 可能返回了一个(可变的)视图而不是一个全新的 numpy 数组。文件系统的往返修复了这个问题,但是一个简单的 .copy() 会产生同样的效果,所以试试吧。
请post在这里回答,让我们知道进展如何。
我找到了问题,结果证明是个好问题。
create_df() 返回的 DataFrame 中的一列具有 dtype 类别。不确定这是怎么发生的,因为它本来就是字符串。该列在分组器中用于聚合。通过将 DataFrame 写入本地文件系统,然后将其读回,该列通过 Pandas 正确地得到 re-interpreted 作为字符串。
使用正确的数据类型,聚合运行 returns 很快,并且没有任何内存问题。我不明白为什么在分类列上分组会导致 OOM 错误——这是另一天的话题。
我无法理解:我有一个函数可以从 S3 存储桶中读取一堆 csv 文件,将它们与 returns DataFrame 连接起来:
def create_df():
df1 = pd.read_csv(s3_path + 'file_1.csv')
df2 = pd.read_csv(s3_path + 'file_2.csv')
return pd.concat([df1, df2], ignore_index=True)
我的第二个函数执行聚合:
def aggregate_values(df):
columns = ['col_c', 'col_d']
new_df = df.groupby(columns, as_index=False) \
.agg({'col_a': 'sum', 'col_b': 'mean'})
return new_df
函数 aggregate_values 由于内存不足错误而失败。
df = create_df()
# OOM error !!!
new_df = aggregate_values(df)
奇怪的是,如果我将 DataFrame 写入我的本地文件系统,然后将其读回,则聚合在新的 DataFrame 上正常工作。
df = create_df()
df.to_csv('path_to_store/f.csv', index=False)
df2 = pd.read_csv('path_to_store/f.csv')
# works fine!!!
new_df = aggregate_values(df2)
我的猜测是 create_df() 返回的 DataFrame 有问题。通过写出来并在 Pandas 中读回以某种方式解决了这个问题。但我想找出 DataFrame 到底出了什么问题。
我该如何调试这个问题?
已编辑
我机器上有32G内存运行代码。 DataFrame 有大约 200 万条记录,占用大约 0.5G 的存储和内存 space.
你没有评论你的内存大小, 也不是 .CSV 或数据框的大小。 但我可以冒险做出一些猜测。 我有几点观察:
- 连接后,您有机会核对 df1 和 df2。只需将
None
分配给它们,即可回收一些 RAM。 - .groupby() 可能接受密集的 numpy 数组并生成 higher-overhead 稀疏数组。你可能想调查一下。
- 计算平均值可能会变成例如
int8
变成float64
,这显然会消耗更多 space。 - 这是最大的项目:.groupby() 可能返回了一个(可变的)视图而不是一个全新的 numpy 数组。文件系统的往返修复了这个问题,但是一个简单的 .copy() 会产生同样的效果,所以试试吧。
请post在这里回答,让我们知道进展如何。
我找到了问题,结果证明是个好问题。
create_df() 返回的 DataFrame 中的一列具有 dtype 类别。不确定这是怎么发生的,因为它本来就是字符串。该列在分组器中用于聚合。通过将 DataFrame 写入本地文件系统,然后将其读回,该列通过 Pandas 正确地得到 re-interpreted 作为字符串。
使用正确的数据类型,聚合运行 returns 很快,并且没有任何内存问题。我不明白为什么在分类列上分组会导致 OOM 错误——这是另一天的话题。