You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spark中拆分对齐DataFrame并在Pandas/Numpy分批读取大Parquet

解决方案

1. 多DataFrame对齐拆分方案(Spark侧)

你可以完全避免使用randomSplit,采用以下两种方案保证多DataFrame拆分后仍行对齐:

  • 方案1:通过控制输出分片大小直接拆分
    Spark原生支持控制单Parquet文件的最大记录数,不会修改数据原有的行顺序,所有行对齐的DataFrame采用同一配置输出即可得到分片一一对应的小文件,完全保证行对齐。
    示例代码:
# 配置单文件最大输出记录数,可根据单行大小调整数值,最终得到的单文件大小约为6GB即可
spark.conf.set("spark.sql.files.maxRecordsPerFile", 1000000)
# 正常写入即可,输出会自动拆分为多个大小均匀的小文件
FULL_MAIN.write.mode("overwrite").parquet(PATH+"/FULL_MAIN.parquet")
  • 方案2:新增行号按范围拆分
    如果需要显式控制拆分逻辑,可以给所有行对齐的DataFrame新增全局唯一的连续行号,按行号范围拆分即可:
from pyspark.sql.functions import row_number, monotonically_increasing_id
from pyspark.sql.window import Window

# 按固定规则生成行号,只要所有DataFrame使用相同的排序规则,生成的行号完全对齐
w = Window.orderBy(monotonically_increasing_id())
FULL_MAIN = FULL_MAIN.withColumn("row_id", row_number().over(w) - 1)
# 按行号范围拆分,比如总共有100万行,拆10份的话每份10万行,所有DataFrame采用同一拆分规则即可保持对齐
split_ranges = [(i*100000, (i+1)*100000) for i in range(10)]
for idx, (start, end) in enumerate(split_ranges):
    split_df = FULL_MAIN.filter((FULL_MAIN.row_id >= start) & (FULL_MAIN.row_id < end)).drop("row_id")
    split_df.write.mode("overwrite").parquet(f"{PATH}/FULL_MAIN_RDD{idx+1}.parquet")

2. pandas/numpy分批读取Parquet方案

无需全量加载即可实现分批读取,推荐使用pyarrow的内置接口,实现逻辑如下:

import pyarrow.parquet as pq

# 打开Parquet文件,不加载全量数据
parquet_file = pq.ParquetFile("/path/to/FULL_MAIN.parquet")
# 按批次迭代读取,batch_size为每次读取的行数,可根据内存大小调整
for batch in parquet_file.iter_batches(batch_size=100000):
    # 转为pandas DataFrame处理
    df_batch = batch.to_pandas()
    # 此处插入你对当前批次的处理逻辑
    # 如果需要转numpy数组,直接调用df_batch.to_numpy()即可

如果不需要读取所有列,可以在iter_batches中指定columns参数,进一步降低内存占用:

for batch in parquet_file.iter_batches(batch_size=100000, columns=["col1", "col2", "col3"]):
    # 仅读取需要的列处理
    ...

内容的提问来源于stack exchange,提问作者Lostsoul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 10:45:05