2017-08-04 50 views
1

我有一个DataFrame如下。在Dataframe中处理空值

Value1 Value2 Value3 
30000 40000 50000 
null 20000 10000 

另外,我有一个UDF创建为

val testUDF=udf((a: Double, b: Double, c: Double) => { 
    if(a==null && b!=null && c!=null) 
     b+c 
    else 
     a+b+c 
}) 

我有一个代码如下。

input.withColumn("checkNull", testUDF(col("value1"),col("value2"),col("value3"))).show 

所得数据帧是

Value1 Value2 Value3 checkNull 
30000 40000 50000 120000 
null 20000 10000 null 

在这里,代替对于第二行显示3000的列 “checkNUll” 时,它显示的,无效。任何我在做我的代码错误? 我不想用0替换它。因为,如果我想在上面进行乘法而不是加法,它将会失败。

+0

您是否尝试过“是空的”和“非空”而不是? – Wonjin

+1

用0替换空值,然后添加。 – philantrovert

+0

是的。 a.isNull抛出一个错误说isNull不是Double的成员 – KishoreKumar

回答

2

有这么多的方式做你正在尝试做的,并与当前的信息,我建议使用​​3210:

df.withColumn("x4", 
        coalesce(
         $"x1".cast("long") * $"x2" * $"x3", 
         $"x2".cast("long") * $"x3", 
         lit(0) 
        ) 
).show 
+-----+-----+-----+--------------+ 
| x1| x2| x3|   x4| 
+-----+-----+-----+--------------+ 
|30000|40000|50000|60000000000000| 
| null|20000|10000|  200000000| 
+-----+-----+-----+--------------+ 

我铸造long由于这个问题Why do these two multiplication operations give different results?

这里是另一个溶液填充柱x1与1相乘:

df.na.fill(1, Seq("x1")).withColumn("x4", $"x1".cast("long") * $"x2" * $"x3").show 

它产生的S结果。

编辑:这是第三个选项来做到这一点:

df.withColumn("x4", 
       when($"x1".isNull and $"x2".isNotNull and $"x3".isNotNull, $"x2".cast("long") * $"x3") 
       .otherwise($"x1".cast("long") * $"x2"* $"x3") 
).show 

编辑2:下面是一些资源来了解Dealing with Null in Apache Spark

+0

第一部分将如何产生'200000000'?将'null'投射到'long'不起作用,是吗?你会不会在第二行得到'0',因为前两个参数'coalesce'会导致'null'? – philantrovert

+0

将null转换为long将产生null,因此第一个表达式为null。我确信这一点。 – eliasah

+1

噢,我想在第二个参数中也是'$“x1”'。我的错。 – philantrovert

0

你必须在这种情况下使用过滤器,因为当value1为null时,它不会调用udf。

val testStr = """[{"Val1":1000, "Val2":2000, "Val3":4000},{"Val2":2000, "Val3":4000}]""" 
    val rdd = sc.parallelize(Seq(testStr)) 
      val df = sqlContext.read.json(rdd) 

      val newdf = df.filter(df.col("Val1").isNotNull).withColumn("checkNull",df.col("Val1")+df.col("Val2")+df.col("Val3")) 
      val newdfw2 = df.filter(df.col("Val1").isNull).withColumn("checkNull",df.col("Val2")+df.col("Val3")) 
      val alldf = newdf.unionAll(newdfw2) 
      alldf.show() 
0

您可以简单地使用na.fill(0.0)全部更换null0.0,只需使用+符号的列值添加为

df.select($"Value1".cast(DoubleType), $"Value2".cast(DoubleType), $"Value3".cast(DoubleType)) 
    .na.fill(0.0) 
    .withColumn("checkNull", $"Value1"+$"Value2"+$"Value3") 
    .show(false) 

鉴于数据帧作为

+------+------+------+ 
|Value1|Value2|Value3| 
+------+------+------+ 
|30000 |40000 |50000 | 
|null |20000 |10000 | 
+------+------+------+ 

你应该有输出为

+-------+-------+-------+---------+ 
|Value1 |Value2 |Value3 |checkNull| 
+-------+-------+-------+---------+ 
|30000.0|40000.0|50000.0|120000.0 | 
|0.0 |20000.0|10000.0|30000.0 | 
+-------+-------+-------+---------+ 

我希望答案有帮助

+0

有没有办法修改我的udf是它? – KishoreKumar

+0

我想你不想要更好的解决方案,对吗? :) –