2017-08-04 89 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

我想你不想要更好的解決方案,對嗎? :) –