Scala:动态连接数据帧

时间:2017-10-04 19:16:59

标签: scala apache-spark foldleft

我将数据拆分为多个文件。我想加载和加入文件。 我想构建一个动态函数 1.将n个数据文件加入单个数据帧 2.给定文件位置和连接列的输入(例如,pk)

我认为这可以用foldLeft完成,但我不太确定如何:

到目前为止,这是我的代码:

@throws
def dataJoin(path:String, fileNames:String*): DataFrame=
{
  try
  {
    val dfList:ArrayBuffer[DataFrame]=new ArrayBuffer
    for(fileName <- fileNames)
    {
      val df:DataFrame=DataFrameUtils.openFile(spark, s"$path${File.separator}$fileName")
      dfList += df
    }

    dfList.foldLeft
    {
             (df,df1) => joinDataFrames(df,df1, "UID")
    }
  }
  catch
  {
    case e:Exception => throw new Exception(e)
  }
}


def joinDataFrames(df:DataFrame,df1:DataFrame, joinColum:String): Unit =
{
  df.join(df1, Seq(joinColum))
}

1 个答案:

答案 0 :(得分:3)

foldLeft可能确实适合这里,但它需要一个“零”元素来开始折叠(除了折叠功能)。在这种情况下,“零”可以是第一个DataFrame:

dfList.tail.foldLeft(dfList.head) { (df1, df2) => df1.join(df2, "UID") }

为了避免错误,您可能希望在尝试访问第一个项目之前确保列表不为空 - 一种方法是使用模式匹配。

dfList match {
  case head :: tail => tail.foldLeft(head) { (df1, df2) => df1.join(df2, "UID") }
  case Nil => spark.emptyDataFrame
}

最后,对于 map 而不是迭代它并填充另一个(空的,可变的)集合,它更简单,更安全,更惯用:

val dfList = fileNames.map(fileName => DataFrameUtils.openFile(spark, s"$path${File.separator}$fileName"))

总而言之:

def dataJoin(path:String, fileNames: String*): DataFrame = {
  val dfList = fileNames
    .map(fileName => DataFrameUtils.openFile(spark, s"$path${File.separator}$fileName"))
    .toList

  dfList match {
    case head :: tail => tail.foldLeft(head) { (df1, df2) => df1.join(df2, "UID") }
    case Nil => spark.emptyDataFrame
  }
}