簡體   English   中英

從一個小文件中查找火花

[英]spark look up from a small file

我正在做一個火花項目,需要關於如何以最佳方式解決以下問題的建議:

我有一個數據框架(說MainDF),它具有數百萬條記錄。 格式是這樣的(name:String,value:Int)。 內容示例如下:

Davi,130
Joel,20
Emma,500

我還有另一個小文件,有4行記錄,像這樣(className:String,minValue:Int,maxValue:Int)現在,我需要通過基於min和max之間的值查找類名來創建文件,輸出為上面的記錄如下:

First,500,9999999
Second,100,499
Third,0,99
Unknown,-99999,0

我需要為MainDF中的每個值查找此小文件,並根據小File中的值范圍添加類名稱。

Davi,130,Second
Joel,20,Third
Emma,500,First

這是我編寫的代碼:

//Main Data read, millions of records
val MainData = sc.textFile("/mainfile.csv")
case class MainType(Name:String,value:Int)
val MainDF = MainData .map(line => line.split(",")).map(e =>MainType(e(0),e(1).toInt))).toDF
MainDF.registerTempTable("MainTable")
val refData = sc.broadast( sc.textFile("/refdata.csv"))
case class refDataType (className:String,minValue:Int,maxValue:Int)
//ref data, just 4 records
val refRDD = refData.map(line=> line.split(",")).map( e => refDataType ( e(0) , e(1).toInt, e(2).toInt))

我想我必須在這里編寫UDF,但是我不知道如何在UDF中使用數據框,或者在spark scala中有什么方法可以做到這一點

您可以使用textFile將其讀取為RDD文件,因為它很小(可以根據需要進行廣播),請收集該文件。

通過收集RDD獲得數組后,可以創建一個Range ,然后創建一個UDF以檢查您的值是否在該范圍內。

val rdd = sc.parallelize(Array(
("First",500,9999999),
("Second",100,499),
("Third",0,99),
("Unknown",-99999,0)
))

val dataArr = rdd.map{ case (className, min, max) => 
                       (className, Range(min, max) )  }.collect
// First Element will be the Class Name
// Second will be the Range(min, max)
// sc.broadcast(dataArr) here

val getClassName = udf {(x: Int) => { 
                  dataArr.map{ e => 
                        if (e._2.contains(x) ) e._1.toString 
                        else null.asInstanceOf[String] }
                  .filter(_ != null )
                  .apply(0) }}

df.withColumn("ClassName", getClassName($"VALUE") ).show
+----+-----+---------+
|NAME|VALUE|ClassName|
+----+-----+---------+
|Davi|  130|   Second|
|Joel|   20|    Third|
|Emma|  500|    First|
+----+-----+---------+

我很肯定可能會有更好的解決方案。

此處最簡單的方法是使用csv數據源讀取兩個文件,然后使用標准SparkSQL將它們加入,如下所示:

import org.apache.spark.sql.types.{StructType, StructField, StringType, IntegerType}
val mainSchema = StructType(Seq(StructField("name", StringType, false), 
StructField("value", IntegerType, false)))
val mainDf = spark.read.schema(mainSchema).csv("/tmp/b.txt")
val lookupSchema = StructType(Seq(StructField("class_name", StringType, false), StructField("min_value", IntegerType, false), 
StructField("max_value", IntegerType, false)))
val lookupDf = spark.read.schema(lookupSchema).csv("/tmp/a.txt")
val result = mainDf.join(lookupDf, $"value" <= $"max_value" && $"value" > $"min_value")
result.show()

我不確定最有效的方式是這種方式還是@philantrovert建議的方式(這也可能取決於您使用的Spark版本)。 您應該同時嘗試它們並自行決定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM