Spark Scala 程序中的隐含功能不起作用

Posted

技术标签:

【中文标题】Spark Scala 程序中的隐含功能不起作用【英文标题】:Implicits in a Spark Scala program not working 【发布时间】:2017-05-31 16:53:42 【问题描述】:

虽然我正在导入 spark.implicits._,但我无法在 Scala 程序中执行从 RDD 到 Dataframe 的隐式转换。

任何帮助将不胜感激。

带有隐式的主程序:

object spark1 

  def main(args: Array[String]) 
    val spark = SparkSession.builder().appName("e1").config("o1", "sv").getOrCreate()

    import spark.implicits._

    val conf = new SparkConf().setMaster("local").setAppName("My App")
    val sc = spark.sparkContext
    val data = sc.textFile("/TestDataB.txt")
    val allSplit = data.map(line => line.split(","))
    case class CC1(LAT: Double, LONG: Double)
    val allData = allSplit.map( p => CC1( p(0).trim.toDouble, p(1).trim.toDouble))
    val allDF = allData.toDF()
    // ... other code
  


错误如下:

错误:(40, 25) 值 toDF 不是 org.apache.spark.rdd.RDD[CC1] 的成员 val allDF = allData.toDF()

【问题讨论】:

大都会,感谢您的清理。马克 【参考方案1】:

当你定义case类CC1在main方法中,你点击https://issues.scala-lang.org/browse/SI-6649;然后toDF() 在编译时无法为该类找到适当的隐式TypeTag

您可以在这个简单的示例中看到这一点:

case class Out()

object TestImplicits 

  def main(args: Array[String]) 
    case class In()
    val typeTagOut = implicitly[TypeTag[Out]] // compiles
    val typeTagIn = implicitly[TypeTag[In]]   // does not compile: Error:(23, 31) No TypeTag available for In
  


Spark的相关隐式转换有这个类型参数:[T <: Product : TypeTag](见newProductEncoderhere),这意味着需要一个隐式TypeTag[CC1]

要解决这个问题 - 只需将 CC1 的定义移出方法,或完全移出对象:

case class CC1(LAT: Double, LONG: Double)

object spark1 

  def main(args: Array[String]) 
    val spark = SparkSession.builder().appName("e1").config("o1", "sv").getOrCreate()

    import spark.implicits._

    val data = spark.sparkContext.textFile("/TestDataB.txt")
    val allSplit = data.map(line => line.split(","))

    val allData = allSplit.map( p => CC1( p(0).trim.toDouble, p(1).trim.toDouble))
    val allDF = allData.toDF()
    // ... other code
  


【讨论】:

注意:编辑了我的答案(第一个版本有正确的修复但错误的解释) Tzach,有道理。谢谢你的帮助,马克 @TzachZohar,@user1154422,关于创建CC1动态类(在运行时,而不是编译时)”的整个想法显然是错误。您可以通过注释掉错误的代码行并查看已编译的.class 文件来验证它。此外,您不必将类 CC1 移动到顶部外部上下文,只需将其移到本地编译上下文之外,即直接在 spark1 对象内就足够了。这似乎与 SI-6649 有关,其中类似的行为被描述为故意(尽管我不明白其中的原因)。【参考方案2】:

我认为toDFsqlContext.implicits._ 中,所以您需要导入它而不是spark.implicits._。至少在 spark 1.6 中是这样的

【讨论】:

以上是关于Spark Scala 程序中的隐含功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

scala用户定义函数在spark sql中不起作用

Spark - Scala:当 json 数据分布在多行时,读取 json 文件作为数据帧不起作用?

Windows上的Spark--rdd.count()不起作用[重复]

在 EMR 中使用 spark ad scala 从 redshift 加载数据

Spark多个动态聚合函数,countDistinct不起作用

Scala Play Framework Slick 会话不起作用