Gegeben ist 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.SparkSQL: Wie mit Nullwerten in benutzerdefinierten Funktion umgehen?
Essential ist zu halten null
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) auf Werte aus der Spalte "X" Umwandlung in die der Spalte „y“ ist:
val extractDateAsInt = udf[Int, String] (
(d:String) => d.substring(0, 10)
.filterNot("-".toSet)
.toInt)
und arbeitet, mit Nullwerten zu tun ist nicht möglich.
Obwohl, ich kann so etwas tun
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, um null
Werte über udfs (natürlich als Int
s nicht null
sein kann) „produzieren“.
Meine aktuelle Lösung für die Erstellung von DF2 (Tabelle 2) ist 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")
Fragen:
- Die aktuelle Lösung scheint umständlich (und wahrscheinlich nicht effizient WRT Leistung.) . Gibt es einen besseren Weg?
- @ Spark-Entwickler: Gibt es einen Typ
NullableInt
geplant/available, so dass das folgende udf möglich ist (siehe Code-Auszug)?
Codeauszug
val extractDateAsNullableInt = udf[NullableInt, String] (
(d:String) =>
if (d != null) d.substring(0, 10).filterNot("-".toSet).toInt
else null)
Einfache Lösung ist geschachtelte Typen zu verwenden: http://stackoverflow.com/questions/42791912/how-to-deal-with-spark-udf-input-output-of-primitive-nullable-type/42791913 # 42791913 –
Einfach Die Lösung besteht darin, geboxte Typen zu verwenden: http://stackoverflow.com/questions/42791912/how-to-deal-with-spark-udf-input-output-of-primitive-nullable-type/42791913#42791913 –