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

Python与Spark Scala处理DataFrame去空行后行数不一致问题排查

问题分析:Pandas与Spark Scala删除指定列空值后行数差异

核心差异根源

你的两段代码逻辑并非完全等价,再加上空值定义、数据本身的差异,最终导致行数结果天差地别:

  • Pandas 多次dropna(subset=[col], inplace=True):逐步过滤每一列的空值行,最终仅保留所有指定列均无空值的行(每一步都剔除对应列的空值行,结果叠加)。
  • Spark Scala na.drop(Seq(cols)):默认使用how="any"规则,会删除指定列中任意一列存在空值的行——看似和Pandas逻辑一致,但两者对"空值"的判定范围、数据预处理环节可能存在差异。

排查与验证步骤

1. 确认原始数据集完全一致

先排除数据源差异:

  • 检查Pandas和Spark的读取逻辑:是否读取了同一文件/数据源?是否有预过滤、分区读取导致的数据缺失?
  • 分别打印原始数据的行数,确认两者处理的是同一份数据。

2. 核对空值定义的差异

Spark和Pandas对"空值"的判定范围不同,这是最常见的原因:

  • Pandas dropna仅识别None、NaN为有效空值,空字符串""、空格字符串" "不会被过滤。
  • Spark na.drop默认仅识别null、NaN,但如果数据中存在大量空字符串,会被当成有效值保留,而Pandas中这些行不会被过滤——反过来,如果Spark中提前把空字符串转为null,结果会和Pandas对齐。

对齐空值处理的验证代码

  • Pandas侧(模拟Spark的空值判定):

    import pandas as pd
    import numpy as np
    
    cols_to_filter = ["model", "engine_type", "aircraft_type", "status", "ArrDelay", "issue_date", "manufacturer", "type", "tailnum", "DepDelay", "TaxiOut"]
    # 将空字符串转为NaN,对齐Spark的空值处理逻辑
    dfplaneairport[cols_to_filter] = dfplaneairport[cols_to_filter].replace("", np.nan)
    # 一次性过滤所有指定列的空值
    df_filtered = dfplaneairport.dropna(subset=cols_to_filter)
    print(df_filtered.shape)
    
  • Spark侧(模拟Pandas的空值判定):

    import org.apache.spark.sql.functions._
    
    val colsToFilter = Seq("engine_type", "aircraft_type", "status", "model", "issue_date", "manufacturer", "type","ArrDelay", "DepDelay", "TaxiOut", "tailnum")
    # 仅过滤指定列中为null/NaN的行,忽略空字符串
    val dfFiltered = dfairports.filter(
      colsToFilter.map(c => col(c).isNotNull && col(c).isNaN === false).reduce(_ && _)
    )
    dfFiltered.count()
    

3. 统一代码逻辑,排除操作差异

将两段代码的过滤逻辑完全对齐:

  • Pandas不要多次调用dropna,改为一次性过滤所有指定列(和Spark逻辑一致):
    cols_to_filter = ["model", "engine_type", ...] # 列出所有需要过滤的列
    df_filtered = dfplaneairport.dropna(subset=cols_to_filter)
    print(df_filtered.shape)
    
  • Spark可以显式指定how="any"(默认就是这个值,用于确认逻辑):
    dfairports = dfairports.na.drop(how="any", subset=Seq("engine_type", ...))
    dfairports.count()
    

4. 检查列名匹配性

确认两段代码中指定的列名完全一致,包括大小写、拼写:

  • 比如Pandas中的ArrDelay和Spark中的arrdelay(大小写不同)会导致过滤的列完全不同,最终结果差异巨大。
  • 分别打印两个DataFrame的列名列表,逐行对比。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 15:35:22