web-dev-qa-db-fra.com

Scala Vérification nulle de la trame de données pour les colonnes

val new_df = df.filter($"type_interne" !== "" || $"type_interne" !== "null")

Donnez-moi une valeur d'erreur || n'est pas membre de la chaîne

Quand j'utilise === fonctionne bien pour le filtre

val new_df = df.filter($"type_interne" === "" || $"type_interne" === "null")
8
Subhod Lagade

Le problème semble être la priorité de l'opérateur, essayez d'utiliser des accolades:

 val new_df = df.filter(($"type_interne" !== "") || ($"type_interne" !== null))

vous pouvez également l'écrire comme ceci:

val new_df = df.filter(($"type_interne" !== "") or $"type_interne".isNotNull)
9
Raphael Roth

Bien que la réponse de Raphaël soit entièrement correcte au moment de la rédaction de cet article, spark evolving ... Operator !== est obsolète depuis la version 2.0, mais vous pouvez utiliser =!= qui résout le problème de priorité ci-dessus sans utiliser de parenthèses. Voir les commentaires correspondants dans le code source: https://github.com/Apache/spark/blob/branch-2.2/sql/core/src/main/scala/org/Apache/spark/sql/Column.scala # L319-L32

Réponse détaillée:
Je voudrais également noter quelque chose qui n'était pas évident pour moi au début. Il existe des notions de DataFrame (DF) et DataSet (DS), qui divisent également leur utilisation dans le contexte ci-dessus en:
1) chaînes interprétées par le catalyseur (les erreurs ne sont rattrapées que lors de l'exécution) - les deux DF et DS classe de cas NullStrings (n : Int, s: String)

val df = spark.sparkContext.parallelize(Seq(
    (1, "abc"),
    (2, "ABC"),
    (3, null),
    (4, ""))
).toDF("n", "s")

df.filter("s is not null and s != ''").show()

+---+---+
|  n|  s|
+---+---+
|  1|abc|
|  2|ABC|
+---+---+

2) syntaxe de trame de données utilisant la notion de Column ($ avec spark.implicits._ import) compilation partiellement vérifiée:

df.filter($"s" =!= "" || $"s" =!= null).show() 

mais en fait =!= ignore les valeurs nulles (voir <=> pour une comparaison sans danger), donc ci-dessous est égal à

df.filter($"s" =!= "").show()

+---+---+
|  n|  s|
+---+---+
|  1|abc|
|  2|ABC|
+---+---+

3) ensemble de données

val ds = df.as[NullStrings]

ds.filter(r => r.s != null && r.s.nonEmpty).show()
+---+---+
|  n|  s|
+---+---+
|  1|abc|
|  2|ABC|
+---+---+

Attention si vous utilisez Option dans la classe case, vous devez y faire face, pas une simple chaîne.

case class NullStringsOption(n: Int, s: Option[String])

val ds1 = df.as[NullStringsOption]

ds1.filter(_.s.exists(_.nonEmpty)).show()
3
Nikita