Spark读取仅首份带表头的多CSV文件如何避免数据丢失或表头入数据行
问题根源
spark.read.csv的header=true参数对所有读取的文件单独生效,即每个文件的第一行都会被当作表头跳过,因此现有写法会导致后4个无表头文件的首行数据丢失。
解决方案
方案1:分两部分读取后合并(最稳妥,无数据误删风险)
逻辑为单独读取带表头的第一个文件,再读取其余无表头的文件并复用前者的schema,最后合并两个DataFrame即可,代码示例:
# 1. 读取第一个带表头的文件,同时获取schema和该文件的有效数据 df_with_header = spark.read \ .format("csv") \ .option("header", "true") \ .option("inferSchema", "true") \ .load("path/file-1") csv_schema = df_with_header.schema # 2. 读取其余4个无表头的文件,指定header=false并复用上面的schema # 此处可以直接传入其余文件的路径列表,也可以用通配符排除第一个文件,根据实际场景调整即可 df_without_header = spark.read \ .format("csv") \ .option("header", "false") \ .schema(csv_schema) \ .load(["path/file-2", "path/file-3", "path/file-4", "path/file-5"]) # 3. 合并两个DataFrame得到全量正确数据 final_df = df_with_header.unionByName(df_without_header)
方案2:全量读取后过滤表头行(适合文件命名不规整、不方便拆分路径的场景)
如果不想拆分文件路径,也可以全量读取时关闭header选项,手动指定schema后过滤掉和表头完全一致的行即可,该方案仅适用于业务数据不会出现和表头完全相同行的场景:
# 1. 读取第一个文件获取schema和表头内容 header_df = spark.read \ .format("csv") \ .option("header", "true") \ .option("inferSchema", "true") \ .load("path/file-1") csv_schema = header_df.schema header_cols = [field.name for field in csv_schema.fields] # 2. 全量读取所有文件,关闭header选项,指定schema all_df = spark.read \ .format("csv") \ .option("header", "false") \ .schema(csv_schema) \ .load("path/") # 3. 过滤掉第一个文件的表头行 final_df = all_df.filter(lambda row: list(row) != header_cols)
内容的提问来源于stack exchange,提问作者callme
相关产品推荐
相关产品推荐

