给定表1,其中一列“x”为String类型。我想创建表2,其中列“y”是“x”中给出的日期字符串的整数表示。
Essential是将null
值保留在“y”列中。
表1(数据框df 1):
+----------+
| x|
+----------+
|2015-09-12|
|2015-09-13|
| null|
| null|
+----------+
root
|-- x: string (nullable = true)
表2(数据框df 2):
+----------+--------+
| x| y|
+----------+--------+
| null| null|
| null| null|
|2015-09-12|20150912|
|2015-09-13|20150913|
+----------+--------+
root
|-- x: string (nullable = true)
|-- y: integer (nullable = true)
而将列“x”的值转换为列“y”的值的用户定义函数(udf)是:
val extractDateAsInt = udf[Int, String] (
(d:String) => d.substring(0, 10)
.filterNot( "-".toSet)
.toInt )
和作品,处理空值是不可能的。
尽管如此,我还是可以做一些
val extractDateAsIntWithNull = udf[Int, String] (
(d:String) =>
if (d != null) d.substring(0, 10).filterNot( "-".toSet).toInt
else 1 )
我没有找到通过udfs“产生”null
值的方法(当然,因为Int
s不能是null
)。
我目前创建df 2的解决方案(表2)如下:
// 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")
问题:
- 目前的解决方案似乎很麻烦(而且可能效率不高)。性能)。有更好的办法吗?
- @Spark-developers:是否有一个类型
NullableInt
计划/可用,这样下面的udf是可能的(见代码摘录)?
代码摘录
val extractDateAsNullableInt = udf[NullableInt, String] (
(d:String) =>
if (d != null) d.substring(0, 10).filterNot( "-".toSet).toInt
else null )
4条答案
按热度按时间wz3gfoph1#
这就是
Option
派上用场的地方:或者在一般情况下使其稍微更安全:
所有的功劳都归功于Dmitriy Selivanov,他指出了这个解决方案是一个(缺失的?)编辑here。
另一种方法是在UDF之外处理
null
:8cdiaqws2#
Scala实际上有一个很好的工厂函数Option(),它可以使这更简洁:
在内部,Option对象的apply方法只是为您执行null检查:
kd3sttzy3#
补充码
有了@zero323的nice答案,我创建了下面的代码,让用户定义的函数可以像描述的那样处理空值。希望对其他人有帮助!
jmo0nnb34#
使用coalesce函数和col参数来提供一个默认值,如果为null
coalesce(a, b, c)
将返回a,yourUDF(coalesce(col(parameter1),lit(defaultValueForParameter 1)