连接多个 Pandas 数据帧时出现内存错误
Memory Error while concatenating multiple Pandas Dataframes
我们正在尝试加载 IDS-2018 dataset,它包含 10 个 CSV 文件,总共 6.4 GB。当我们尝试在 32GB RAM 服务器中连接所有 CSV 文件时,它崩溃了(进程被终止)。
我们甚至尝试通过使用
优化pandas数据帧中的存储space
def reduce_mem_usage(df):
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
start_mem = df.memory_usage().sum() / 1024**2
for col in df.columns:
col_type = df[col].dtypes
if col_type in numerics:
c_min = df[col].min()
c_max = df[col].max()
if str(col_type)[:3] == 'int':
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
df[col] = df[col].astype(np.int64)
else:
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
end_mem = df.memory_usage().sum() / 1024**2
print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
return df
但是没有用。服务器在连接每个 CSV 文件时仍然崩溃。我们使用 pd.concat
连接了每个文件。整个代码是 here。如何做到这一点,以便我们做进一步的处理??
我会尝试以下方法:
- 通过 dtypes 参数在
read_csv
上指定列类型。
- 未创建 10 个数据帧并依赖于
del
。
import numpy as np
import pandas as pd
data_files = [
'./data/CSVs/02-14-2018.csv',
'./data/CSVs/02-15-2018.csv',
... # a few more
]
# define dtypes
data_types = {
"col_a": np.float64,
... # other types
}
df = reduce_memory_usage(
pd.read_csv(filename[0], dtype=data_types, index_col=False)
)
for filename[1:] in data_files:
df = pd.concat(
[
df,
reduce_mem_usage(
pd.read_csv(
filename,
dtype=data_types,
index_col=False,
)
),
],
ignore_index=True,
)
通过这种方式,您可以确保类型推断正是您所需要的,并减少内存占用。此外,如果您的数据中有分类列,这些列通常在 CSV 文件中编码为字符串,您可以通过使用分类列数据类型大大减少内存占用。
我们正在尝试加载 IDS-2018 dataset,它包含 10 个 CSV 文件,总共 6.4 GB。当我们尝试在 32GB RAM 服务器中连接所有 CSV 文件时,它崩溃了(进程被终止)。
我们甚至尝试通过使用
优化pandas数据帧中的存储space
def reduce_mem_usage(df):
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
start_mem = df.memory_usage().sum() / 1024**2
for col in df.columns:
col_type = df[col].dtypes
if col_type in numerics:
c_min = df[col].min()
c_max = df[col].max()
if str(col_type)[:3] == 'int':
if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
df[col] = df[col].astype(np.int8)
elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
df[col] = df[col].astype(np.int16)
elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
df[col] = df[col].astype(np.int32)
elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
df[col] = df[col].astype(np.int64)
else:
if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
df[col] = df[col].astype(np.float16)
elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
df[col] = df[col].astype(np.float32)
else:
df[col] = df[col].astype(np.float64)
end_mem = df.memory_usage().sum() / 1024**2
print('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
print('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
return df
但是没有用。服务器在连接每个 CSV 文件时仍然崩溃。我们使用 pd.concat
连接了每个文件。整个代码是 here。如何做到这一点,以便我们做进一步的处理??
我会尝试以下方法:
- 通过 dtypes 参数在
read_csv
上指定列类型。 - 未创建 10 个数据帧并依赖于
del
。
import numpy as np
import pandas as pd
data_files = [
'./data/CSVs/02-14-2018.csv',
'./data/CSVs/02-15-2018.csv',
... # a few more
]
# define dtypes
data_types = {
"col_a": np.float64,
... # other types
}
df = reduce_memory_usage(
pd.read_csv(filename[0], dtype=data_types, index_col=False)
)
for filename[1:] in data_files:
df = pd.concat(
[
df,
reduce_mem_usage(
pd.read_csv(
filename,
dtype=data_types,
index_col=False,
)
),
],
ignore_index=True,
)
通过这种方式,您可以确保类型推断正是您所需要的,并减少内存占用。此外,如果您的数据中有分类列,这些列通常在 CSV 文件中编码为字符串,您可以通过使用分类列数据类型大大减少内存占用。