2

首先,由于三值逻辑,这不仅仅是对空或空检查的任何有效实现的否定。

我想做一个函数isNotNullish,它尽可能接近 isNotNull 但也过滤掉空字符串。我遇到了一些奇怪的问题,涉及列/列类型的工作方式以及三值逻辑。到目前为止,我拥有的最好的是:

def isNotNullish(questionable: Column) : Column = {
  val oddish = questionable === lit("")
  questionable.isNotNull && (!oddish || oddish.isNull)
}

如果这看起来很奇怪,那是因为它是。据我所知,如果该行包含 null 或(一些!)非字符串类型,questionable === lit("")将返回给定行。null在三值逻辑中,在某些我希望它返回的情况下true && null = null,这会导致questionable.isNotNull && (questionable =!= lit("")返回。代码永远不应产生空值,始终为真或假。nulltruequestionable.isNotNull && (!oddish || oddish.isNull)

这几乎不是很有效:出于某种我不明白的原因,=== 比较很高兴为数字类型返回 null,但对于复杂类型则失败。(即使我试图做的事情是不可能或不可取的,我也希望对此作出解释。)

检查架构并简单地对字符串类型进行与其他类型不同的测试可能更负责,但据我所知,这需要将数据帧作为参数传递。我试图避免这种情况,特别是对于所述参数可能是匿名的长序列转换。

(在有人问之前,我知道以这种草率的方式处理 null 和类型在一般 scala 中会很糟糕,但我认为它在 Spark/SQL/不同模式的巨大数据帧的上下文中是不同的。具体情况是自动探索粗略数据,因此能够回答诸如“我不知道这些列是什么,但告诉我它们保持实际值的频率”之类的问题很有用。)

4

1 回答 1

3

这对你有用吗<=>

    val employees = spark.createDataFrame(Seq(("E1","100.0"), ("E2","200.0"),("E3",null),("E4",""))).toDF("employee","salary")
    employees.show()
    employees.filter(notNullAndEmpty($"salary")).show()

  def notNullAndEmpty(c:Column): Column ={
    (c.isNotNull and !(c <=> lit("")))
  }

数据 -

+--------+------+
|employee|salary|
+--------+------+
|      E1| 100.0|
|      E2| 200.0|
|      E3|  null|
|      E4|      |
+--------+------+

结果

+--------+------+
|employee|salary|
+--------+------+
|      E1| 100.0|
|      E2| 200.0|
+--------+------+
于 2020-02-13T18:20:44.547 回答