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]
(见newProductEncoder
here),这意味着需要一个隐式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】:
我认为toDF
在sqlContext.implicits._
中,所以您需要导入它而不是spark.implicits._
。至少在 spark 1.6 中是这样的
【讨论】:
以上是关于Spark Scala 程序中的隐含功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Spark - Scala:当 json 数据分布在多行时,读取 json 文件作为数据帧不起作用?
Windows上的Spark--rdd.count()不起作用[重复]
在 EMR 中使用 spark ad scala 从 redshift 加载数据