如何有效地生成具有列表(1000个条目)的Spark数据帧(100万行)笛卡尔积,以生成具有10亿行的新数据帧

时间:2017-02-07 10:31:08

标签: scala apache-spark dataframe rdd

我想通过采用具有1000个条目的列表的交叉积来获取具有100万行并且从其每行生成1000行的数据帧的每一行,从而生成具有10亿行的数据帧。有效地做到这一点的最佳方法是什么。 我已尝试广播列表,然后在映射数据帧的每一行时使用它。但这似乎花了太多时间。

 val mappedrdd = validationDataFrames.map(x => {
     val cutoffList : List[String] = cutoffListBroadcast.value
     val arrayTruthTableVal = arrayTruthTableBroadcast.value

     var listBufferRow: ListBuffer[Row] = new ListBuffer()

       for(cutOff <- cutoffList){
          val conversion = x.get(0).asInstanceOf[Int]
          val probability = x.get(1).asInstanceOf[Double]

          var columnName : StringBuffer = new StringBuffer
          columnName = columnName.append(conversion)

          if(probability > cutOff.toDouble){
              columnName = columnName.append("_").append("1")
          }else{
              columnName = columnName.append("_").append("0")
          }
          val index:Int  = arrayTruthTableVal.indexOf(columnName.toString)
          var listBuffer : ListBuffer[String] = new ListBuffer()
          listBuffer :+= cutOff

          for(i <- 1 to 4){
             if((index + 1) == i) listBuffer :+= "1" else listBuffer :+= "0"
          }
          val row = Row.fromSeq(listBuffer)
          listBufferRow = listBufferRow :+ row
        }

      listBufferRow

     })

1 个答案:

答案 0 :(得分:2)

根据您的火花版本,您可以:

Spark 2.1.0

将列表添加为列并展开。一个简化的例子:

val df = spark.range(5)
val exploded = df.withColumn("a",lit(List(1,2,3).toArray)).withColumn("a", explode($"a"))
df.show()

+---+---+
| id|  a|
+---+---+
|  0|  1|
|  0|  2|
|  0|  3|
|  1|  1|
|  1|  2|
|  1|  3|
|  2|  1|
|  2|  2|
|  2|  3|
|  3|  1|
|  3|  2|
|  3|  3|
|  4|  1|
|  4|  2|
|  4|  3|
+---+---+

您可以这样做:

def time[R](block: => R): Long = {
    val t0 = System.currentTimeMillis()
    block    // call-by-name
    val t1 = System.currentTimeMillis()
    t1 - t0
 }
  time(spark.range(1000000).withColumn("a",lit((0 until 1000).toArray)).withColumn("a", explode($"a")).count())

在16核计算机上花了5.41秒,内存充足,默认并行度为60。

<强>&LT; Spark 2.1.0

您可以定义一个简单的UDF。

 val xx = (0 until 1000).toArray.toSeq // replace with your list but turn it to seq
  val ff = udf(() => {xx})
  time(spark.range(1000000).withColumn("a",ff()).withColumn("a", explode($"a")).count())

与上述8.25秒相同的服务器