首页 > 解决方案 > 用另一个字符串替换正则表达式模式有效,但用 NONE 替换会替换所有值

问题描述

我正在尝试用 NULL 值替换以“DEL_”开头的列中的所有字符串。

我试过这个:

customer_details = customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", ""))

哪个按预期工作,新列现在如下所示:

+--------------+
|  phone_number|
+--------------+
|00971585059437|
|00971559274811|
|00971559274811|
|              |
|00918472847271|
|              |
+--------------+

但是,如果我将代码更改为:

customer_details = customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", None))

这现在替换列中的所有值:

+------------+
|phone_number|
+------------+
|        null|
|        null|
|        null|
|        null|
|        null|
|        null|
+------------+

标签: regexapache-sparkpyspark

解决方案


尝试这个-

斯卡拉

df.withColumn("phone_number", when(col("phone_number").rlike("^DEL_.*"), null)
          .otherwise(col("phone_number"))
      )

Python

df.withColumn("phone_number", when(col("phone_number").rlike("^DEL_.*"), None)
          .otherwise(col("phone_number"))
      )

Update

询问-

你能解释一下为什么我原来的解决方案不起作用吗?customer_details.withColumn("phone_number", F.regexp_replace("phone_number", "DEL_.*", None))

Ans-所有三元表达式(带 3 个参数的函数)都是null-safe. 这意味着如果 spark 找到任何参数null,它确实会在没有任何实际处理的情况下返回 null(例如,regexp_replace 的模式匹配)。你可能想看看这个 spark repo

  override def eval(input: InternalRow): Any = {
    val exprs = children
    val value1 = exprs(0).eval(input)
    if (value1 != null) {
      val value2 = exprs(1).eval(input)
      if (value2 != null) {
        val value3 = exprs(2).eval(input)
        if (value3 != null) {
          return nullSafeEval(value1, value2, value3)
        }
      }
    }
    null
  }

推荐阅读