2017-05-29 106 views
0

假設我有一個數據幀,其列名爲x,取值範圍爲[0, 1]。我希望將其分割爲x列的值,範圍如[0, 0.1)[0.1, 0.2) ... [0.9, 1]。有沒有一個好的和快速的方法來做到這一點?我在斯卡拉使用Spark 2。Spark Scala將數據幀分割成若干取值範圍

更新:理想情況下,應該有10個新的數據框包含每個範圍的數據。

回答

0

擴大對@ Psidom的創建範圍的解決方案,這裏有一個方法來創建一個數據幀每個範圍:

import org.apache.spark.sql.types.IntegerType 
val df = Seq(0.2, 0.71, 0.95, 0.33, 0.28, 0.8, 0.73).toDF("x") 
val df2 = df.withColumn("g", ($"x" * 10.0).cast(IntegerType)) 

df2.show 
+----+---+ 
| x| g| 
+----+---+ 
| 0.2| 2| 
|0.71| 7| 
|0.95| 9| 
|0.33| 3| 
|0.28| 2| 
| 0.8| 8| 
|0.73| 7| 
+----+---+ 

val dfMap = df2.select($"g").distinct. 
    collect. 
    flatMap(_.toSeq). 
    map(g => g -> df2.where($"g" === g)). 
    toMap 

dfMap.getOrElse(3, null).show 
+----+---+ 
| x| g| 
+----+---+ 
|0.33| 3| 
+----+---+ 

dfMap.getOrElse(7, null).show 
+----+---+ 
| x| g| 
+----+---+ 
|0.71| 7| 
|0.73| 7| 
+----+---+ 

[更新]

如果你的範圍是不規則的,您可以定義一個雙映射到相應的INT範圍ID的功能,然後在下面用UDF包住它,如:

val g: Double => Int = x => x match { 
    case x if (x >= 0.0 && x < 0.12345) => 1 
    case x if (x >= 0.12345 && x < 0.4834) => 2 
    case x if (x >= 0.4834 && x < 1.0) => 3 
    case _ => 99 // catch-all 
} 

val groupUDF = udf(g) 

val df = Seq(0.1, 0.2, 0.71, 0.95, 0.03, 0.09, 0.44, 5.0).toDF("x") 
val df2 = df.withColumn("g", groupUDF($"x")) 

df2.show 
+----+---+ 
| x| g| 
+----+---+ 
| 0.1| 1| 
| 0.2| 2| 
|0.71| 3| 
|0.95| 3| 
|0.03| 1| 
|0.09| 1| 
|0.44| 2| 
| 5.0| 99| 
+----+---+ 
+0

你能解釋一下dfMap嗎?你認爲這種方式是有效的嗎?謝謝! –

+0

用於創建'dfMap'的變換是一個'Map',它具有不同的'g'作爲鍵和數據框(具有相應的'g')作爲值,涉及將不同的'g'收集到本地數組中,轉換成列表,併爲列表中的每個元素創建一個過濾數據框的「Map」。這些轉換適用於整個數據集,因此並不便宜。如果您打算在'dfMap'中對選定的數據框執行大量計算,我會說他們值得做。 –

+0

我明白你的意思了。我試圖做的是計算每個類別的x的總和('g'在這裏)。有沒有什麼好的方法可以做到這一點? –

0

如果你的意思是離散雙類型化的列,你可能只是做到這一點(乘以10列,然後將它轉換爲整型,列將被切割成10個離散箱):

import org.apache.spark.sql.types.IntegerType 

val df = Seq(0.32, 0.5, 0.99, 0.72, 0.11, 0.03).toDF("A") 
// df: org.apache.spark.sql.DataFrame = [A: double] 

df.withColumn("new", ($"A" * 10).cast(IntegerType)).show 
+----+---+ 
| A|new| 
+----+---+ 
|0.32| 3| 
| 0.5| 5| 
|0.99| 9| 
|0.72| 7| 
|0.11| 1| 
|0.03| 0| 
+----+---+ 
+1

我想10個新的數據幀,並做一些進一步的計算。我正在考慮使用'.filter()',但我不確定這是否有效,並且速度足夠快(數據量很大)。 –

+0

而不是創建10個新的數據框,您可能需要'groupBy(「new」)',然後爲每個組做所需的任何操作。 – Psidom

+0

我會盡力的! –