拆分Pandas列及Parquet时间戳时遇MemoryError,求内存优化方案
大Parquet文件拆分timestamp列的内存优化方案
针对1.28亿行Parquet文件拆分timestamp列时出现的MemoryError,以下是几种实用的内存优化处理方法:
1. 分块读取+逐块处理
一次性加载全量数据到内存是内存溢出的核心原因,改用分块读取Parquet文件,逐块处理后输出:
方案A:分块处理后合并(需全量DataFrame时用)
import pandas as pd # 按100万行分块(可根据自身内存调整大小) chunk_size = 1_000_000 processed_chunks = [] for chunk in pd.read_parquet("your_source_file.parquet", chunksize=chunk_size): # 用字符串切片替代str.split,速度更快内存占用更低 chunk['Date'] = chunk['timestamp'].str[:10] chunk['Time'] = chunk['timestamp'].str[11:] processed_chunks.append(chunk) # 合并所有分块 final_df = pd.concat(processed_chunks, ignore_index=True) # 写入处理后的Parquet文件 final_df.to_parquet("your_processed_file.parquet")
方案B:逐块直接写入(无需全量DataFrame时优先用)
这种方式全程不保留全量数据,内存占用最低:
import pandas as pd chunk_size = 1_000_000 is_first_chunk = True for chunk in pd.read_parquet("your_source_file.parquet", chunksize=chunk_size): chunk['Date'] = chunk['timestamp'].str[:10] chunk['Time'] = chunk['timestamp'].str[11:] # 第一次写入用覆盖模式,后续用追加模式 chunk.to_parquet( "your_processed_file.parquet", mode="w" if is_first_chunk else "a", engine="pyarrow" ) is_first_chunk = False
2. 用PyArrow底层API处理
PyArrow对大Parquet文件的内存管理比Pandas更高效,无需转换为DataFrame即可完成处理:
import pyarrow as pa import pyarrow.parquet as pq from pyarrow import compute as pc # 读取Parquet数据集 dataset = pq.ParquetDataset("your_source_file.parquet") table = dataset.read() # 按'T'拆分timestamp列,最多拆分1次 split_result = pc.split_pattern(table['timestamp'], 'T', max_splits=1) # 提取日期和时间部分 date_col = pc.list_element(split_result, 0) time_col = pc.list_element(split_result, 1) # 将新列添加到原表 new_table = table.append_column('Date', date_col).append_column('Time', time_col) # 写入处理后的Parquet文件 pq.write_table(new_table, "your_processed_file.parquet")
3. 转换为datetime类型后提取日期时间
timestamp是标准ISO格式,先转为datetime类型再提取日期时间,比字符串拆分更高效且内存占用更低:
import pandas as pd chunk_size = 1_000_000 is_first_chunk = True for chunk in pd.read_parquet("your_source_file.parquet", chunksize=chunk_size): # 转换为带时区的datetime类型 chunk['timestamp'] = pd.to_datetime(chunk['timestamp'], utc=True) # 提取日期和时间(可根据需求选择格式) chunk['Date'] = chunk['timestamp'].dt.strftime('%Y-%m-%d') chunk['Time'] = chunk['timestamp'].dt.strftime('%H:%M:%S%z') chunk.to_parquet( "your_processed_file.parquet", mode="w" if is_first_chunk else "a", engine="pyarrow" ) is_first_chunk = False
4. 只加载必要列
如果原Parquet文件包含大量无关列,读取时仅加载timestamp及需要保留的列,进一步降低内存占用:
import pandas as pd # 指定需要加载的列(替换为你的实际列名) required_cols = ['timestamp', 'col1', 'col2'] chunk_size = 1_000_000 is_first_chunk = True for chunk in pd.read_parquet("your_source_file.parquet", usecols=required_cols, chunksize=chunk_size): chunk['Date'] = chunk['timestamp'].str[:10] chunk['Time'] = chunk['timestamp'].str[11:] chunk.to_parquet( "your_processed_file.parquet", mode="w" if is_first_chunk else "a", engine="pyarrow" ) is_first_chunk = False
内容的提问来源于stack exchange,提问作者Suhail
相关产品推荐
相关产品推荐

