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

PySpark DataFrame词频统计时空白字符串的排查与过滤方法

PySpark词频统计空白异常值排查与解决

你写的清洗正则[^a-zA-Z]+?会删除所有非英文字母字符,所有纯符号、纯数字、带标点的词在清洗后会直接变成空字符串,这就是空值计数从423涨到3027的根本原因,和原始数据无关。

1、查看不可见字符串内容与Unicode编码的方法

默认的show()方法会把所有空白类字符渲染成普通空格,无法区分具体类型,用下面两种方式排查:

  • 加边界标记看真实长度和内容
    给待排查的字符串前后加固定标记,配合长度判断,就能看出是不是真的空串、有没有隐藏字符:
    from pyspark.sql.functions import length, concat, lit, col
    # 筛选长度小于3的疑似空白词,加边界标记输出
    df2.filter(length(col("words")) < 3) \
       .withColumn("debug_content", concat(lit("[START]"), col("words"), lit("[END]"))) \
       .withColumn("str_length", length(col("words"))) \
       .show(20, truncate=False)
    
    如果输出里[START]和[END]中间看不到内容但长度大于0,就说明存在不可见字符。
  • 打印字符Unicode编码定位具体字符
    写UDF把字符串拆解成每个字符的Unicode编码,直接看到底是什么字符:
    from pyspark.sql.functions import udf
    from pyspark.sql.types import ArrayType, StringType
    
    get_codepoint = udf(lambda s: [f"U+{ord(c):04X}" for c in s], ArrayType(StringType()))
    df2.filter(length(col("words")) < 3) \
       .withColumn("codepoints", get_codepoint(col("words"))) \
       .select("words", "codepoints") \
       .show(20, truncate=False)
    
    新闻标题里常见的不可见空白一般是:不间断空格U+00A0、全角空格U+3000、零宽空格U+200B、制表符/换行符U+0009/U+000A,或者特殊符号、emoji拆分后残留的控制字符。

2、正确过滤异常空白字符串的方案

你最初出现空值的核心原因是拆分逻辑有问题:直接用split(' ')按单个空格拆分时,如果标题存在连续空格、首尾空格,就会拆出空字符串,比如"hello world"(两个空格)拆分后会得到["hello", "", "world"]。按下面步骤处理可以彻底解决空值问题:

  • 第一步:拆分前标准化标题空白
    先把所有类型的空白字符统一替换成普通空格,去掉首尾空格,再按任意空白正则拆分,从源头避免拆分出空串:
    from pyspark.sql.functions import split, explode, trim, regexp_replace, lower, length
    import nltk
    nltk.download('stopwords')
    from nltk.corpus import stopwords
    
    # 标准化所有空白字符,trim首尾空格
    df_process = df.withColumn("title", trim(regexp_replace(col("title"), r"\s+", " ")))
    # 按任意空白拆分,自动跳过连续空白,不会产生空串
    df_words = df_process.withColumn("words", explode(split(col("title"), r"\s+"))) \
                         .select("words")
    
  • 第二步:优化单词清洗逻辑
    不要直接删除所有非字母字符,只去掉单词首尾的标点,保留单词中间的合法字符(比如U.S.、don't里的点和撇号),避免正常词汇被洗成空串:
    # 移除单词首尾的非字母字符
    df_words = df_words.withColumn("words", regexp_replace(col("words"), r"^[^a-zA-Z]+|[^a-zA-Z]+$", ""))
    # 过滤长度为0的空串
    df_words = df_words.filter(length(col("words")) > 0)
    
  • 第三步:过滤停用词+残留特殊字符
    统一转小写匹配停用词,避免手动维护大小写版本的停用词表,再额外过滤Unicode分类下的所有空白、控制字符残留:
    stoplist = set(stopwords.words('english') + ['|','—','-','–'])
    # 移除所有Unicode空白、控制类字符
    df_words = df_words.withColumn("words", regexp_replace(col("words"), r"[\p{Z}\p{C}]", "")) \
                       .filter(length(col("words")) > 0)
    # 过滤停用词后统计词频
    word_count = df_words.filter(~lower(col("words")).isin(stoplist)) \
                         .groupBy("words") \
                         .count() \
                         .orderBy("count", ascending=False)
    word_count.show()
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:25:33