PySpark读取CSV时badRecordsPath生效后DataFrame计数异常问题
问题解答
这是预期行为吗?
是的,这是PySpark结合badRecordsPath时的预期行为。具体原因:
- Spark读取CSV时默认使用
PERMISSIVE(容错)模式,当你指定badRecordsPath但未修改模式时,所有Schema不匹配的坏记录会被写入指定的坏数据路径,但这些记录并不会被从DataFrame中移除,而是被保留为所有字段值都是null的行。 - 所以
df.show()看不到有效内容(全是null),而df.count()统计的是包含这些null行的总行数,和原文件行数一致。
怎么获取正确的有效数据计数?
有两种实用方法:
方法1:手动过滤全null记录
通过filter筛选出至少有一个字段非null的记录,再统计数量:
# 示例:假设schema包含col1、col2、col3三个字段 valid_df = df.filter(df.col1.isNotNull() | df.col2.isNotNull() | df.col3.isNotNull()) print(valid_df.count()) # 如果字段较多,可以动态生成过滤条件,不用逐个写 from pyspark.sql.functions import col valid_df = df.filter(" OR ".join([f"{col_name}.isNotNull()" for col_name in df.columns])) print(valid_df.count())
方法2:设置mode="DROPMALFORMED"自动过滤
读取文件时加上mode="DROPMALFORMED"参数,Spark会自动过滤掉Schema不匹配的坏记录,同时把这些坏记录写入badRecordsPath,此时df.count()直接返回有效数据的行数:
df = ( spark.read.format(file_type) .schema(schema) .option("badRecordsPath", f"/tmp/badrecords/") .option("header", True) .option("encoding", "iso-8859-1") .option("sep", ",") .option("mode", "DROPMALFORMED") # 新增该参数 .load(file_path) ) print(df.count()) # 此时返回的就是有效数据的数量 df.show() # 仅显示有效数据
两种方式的区别:PERMISSIVE模式保留null行(方便后续排查),DROPMALFORMED直接过滤坏记录,可根据业务需求选择。
内容的提问来源于stack exchange,提问作者Tarique
相关产品推荐
相关产品推荐

