导入sqlContext后,Spark toDF无法解析符号

时间:2016-03-28 08:45:50

标签: scala apache-spark dataframe apache-spark-sql

我正在为Scala Spark应用程序编写一些单元测试 为此,我需要在测试中创建不同的数据帧。所以我写了一个非常简短的DFsBuilder代码,它基本上允许我添加新行并最终创建DF。代码是:

class DFsBuilder[T](private val sqlContext: SQLContext, private val columnNames: Array[String]) {
  var rows = new ListBuffer[T]()

  def add(row: T): DFsBuilder[T] = {
    rows += row
    this
  }

  def build() : DataFrame = {
    import sqlContext.implicits._
    rows.toList.toDF(columnNames:_*) // UPDATE: added :_* because it was accidently removed in the original question
  }
}

但是,toDF方法无法使用无法解析符号toDF进行编译。

我用泛型编写了这个构建器代码,因为我需要创建不同类型的DF(不同数量的列和不同的列类型)。我想用它的方法是在单元测试中定义一些特定的case类,并将它用于构建器

我知道这个问题在某种程度上与我使用泛型(可能是某种类型的擦除问题)的事实有关,但我无法完全理解问题是什么

所以我的问题是:

  • 有人能告诉我问题出在哪里吗?并希望如何解决它
  • 如果这个问题无法通过这种方式解决,有人可能会提供另一种优雅的方式来创建数据帧吗? (我不想用创建代码污染我的单元测试)

我显然首先搜索了这个问题,但只找到了人们忘记导入sqlContext.implicits方法的例子,或者是关于案例类的一些例子,这可能与我没有相同的问题

提前致谢

1 个答案:

答案 0 :(得分:1)

如果您查看toDFSQLImplicits.localSeqToDataFrameHolder的签名(这是使用的隐式函数),您将能够检测到两个问题:

  1. 类型T必须是Product的子类(所有案例类的超类,元组...),并且必须为它提供隐式TypeTag。要解决此问题 - 将类的声明更改为:

    class DFsBuilder[T <: Product : TypeTag](...) { ... }
    
  2. columnNames参数不是Array类型,它是&#34;重复参数&#34; (比如Java&#34; varargs&#34;,请参阅第4.6.2节here),因此您必须将数组转换为参数:

    rows.toList.toDF(columnNames: _*)
    
  3. 通过这两项更改,您的代码可以编译(并且可以正常工作)。