SparkSQL: Wie gehe ich mit Nullwerten in einer benutzerdefinierten Funktion um?
Gegeben Tabelle 1 mit einer Spalte "x" vom Typ String. Ich möchte Tabelle 2 mit einer Spalte "y" erstellen, die eine ganzzahlige Darstellung der in "x" angegebenen Datumszeichenfolgen ist.
Wesentlic soll @ behaltnull
Werte in Spalte "y".
Tabelle 1 (Datenrahmen df1):
+----------+
| x|
+----------+
|2015-09-12|
|2015-09-13|
| null|
| null|
+----------+
root
|-- x: string (nullable = true)
Tabelle 2 (Datenrahmen df2):
+----------+--------+
| x| y|
+----------+--------+
| null| null|
| null| null|
|2015-09-12|20150912|
|2015-09-13|20150913|
+----------+--------+
root
|-- x: string (nullable = true)
|-- y: integer (nullable = true)
Während die benutzerdefinierte Funktion (udf) zum Konvertieren von Werten aus der Spalte "x" in die Werte der Spalte "y" wie folgt lautet:
val extractDateAsInt = udf[Int, String] (
(d:String) => d.substring(0, 10)
.filterNot( "-".toSet)
.toInt )
und funktioniert, es ist nicht möglich, mit Nullwerten umzugehen.
Auch wenn ich so etwas tun kann wie
val extractDateAsIntWithNull = udf[Int, String] (
(d:String) =>
if (d != null) d.substring(0, 10).filterNot( "-".toSet).toInt
else 1 )
Ich habe keine Möglichkeit gefunden, @ "zu produzieren&quonull
-Werte über udfs (natürlich alsInt
s kann nicht @ senull
).
Meine aktuelle Lösung zur Erstellung von df2 (Tabelle 2) lautet wie folgt:
// holds data of table 1
val df1 = ...
// filter entries from df1, that are not null
val dfNotNulls = df1.filter(df1("x")
.isNotNull)
.withColumn("y", extractDateAsInt(df1("x")))
.withColumnRenamed("x", "right_x")
// create df2 via a left join on df1 and dfNotNull having
val df2 = df1.join( dfNotNulls, df1("x") === dfNotNulls("right_x"), "leftouter" ).drop("right_x")
Frage:
Die aktuelle Lösung scheint umständlich (und wahrscheinlich nicht effizient bezüglich Leistung). Gibt es einen besseren Weg?@ Spark-Entwickler: Gibt es einen TypNullableInt
geplant / verfügbar, so dass folgendes udf möglich ist (siehe Code-Auszug)?Code Auszug
val extractDateAsNullableInt = udf[NullableInt, String] (
(d:String) =>
if (d != null) d.substring(0, 10).filterNot( "-".toSet).toInt
else null )