运行“stats()”的 Spark 错误:找不到参数 num 的隐式值:Numeric [Double]

Posted

技术标签:

【中文标题】运行“stats()”的 Spark 错误:找不到参数 num 的隐式值:Numeric [Double]【英文标题】:Spark Error Running "stats()": could not find implicit value for parameter num: Numeric[Double] 【发布时间】:2017-11-09 02:54:25 【问题描述】:

刚写了一些 MapReduce 作业后,我正在学习 spark/scala。

我写了一些 java bean 来帮助我在 HDFS 中解析一个文件,我想用它来帮助加快我在 spark 中的进度。

我已经成功加载了我的文件并创建了一个 java bean 对象数组:

val input = sc.textFile("hdfs://host:port/user/test/path/out")
import my.package.Record
val clust_recs = clv_input.map(line => new my.package.Record(line))
clust_recs.map(rec => rec.getPremium()).stats()

但是最后一行会产生这个错误:

<console>:46: error: could not find implicit value for parameter num: Numeric[Double]

我已经测试了这个字段中的值都是有效的,所以我很确定我没有任何可能导致这个错误的空值。

这是一个值的例子:

val dblArray = clust_recs.map(rec => rec.getPremium()).filter(!isNaN(_))
dblArray.take(10)

输出:

res82: Array[Double] = Array(1250.6, 433.72, 567.07, 219.24, 310.32, 2173.48, 195.0, 697.94, 711.46, 42.718050000000005)

我不知道如何解决这个错误,想知道我是否应该放弃使用我已经创建的 JavaBean 对象的概念。

【问题讨论】:

my.package.Record 是案例类吗? 不,my.package.Record 是一个 Java 类(传统的 java bean,带有 getter 和 setter) Record.getPremium()的签名是什么? 什么是 Spark 版本? 【参考方案1】:

您只能通过隐式转换 RDD[Double]RDD[T] 来期望 stats 运算符在 RDD[T] 上可用,其中 T 可以转换为 Numeric[T](请参阅 the code):

implicit def doubleRDDToDoubleRDDFunctions(rdd: RDD[Double]): DoubleRDDFunctions = 
  new DoubleRDDFunctions(rdd)


implicit def numericRDDToDoubleRDDFunctions[T](rdd: RDD[T])(implicit num: Numeric[T])
  : DoubleRDDFunctions = 
  new DoubleRDDFunctions(rdd.map(x => num.toDouble(x)))

DoubleRDDFunctions的scaladoc中也提到了隐式转换:

通过隐式转换在 Doubles 的 RDD 上可用的额外函数。

关键是下面这行没有给你RDD[Double],而是别的东西

clust_recs.map(rec => rec.getPremium())

这就是下面编译错误的原因:

错误:找不到参数 num 的隐式值:Numeric[Double]

Scala 编译器找不到称为numNumeric[Double] 隐式转换。

implicit def numericRDDToDoubleRDDFunctions[T](rdd: RDD[T])(implicit num: Numeric[T])
  : DoubleRDDFunctions = 
  new DoubleRDDFunctions(rdd.map(x => num.toDouble(x)))

我只能猜测 Double 是 Java 的 java.lang.Double 而不是 Scala 的 Double,因此会出现编译错误。

【讨论】:

【参考方案2】:

感谢 Jacek 让我找到正确的方向,您的回答让我更多地了解如何在 map 函数中将 java.lang.Double 转换为 scala.Double。

作为 scala 的新用户,我正在努力处理与 Java 的差异,尤其是隐式转换。

我发现这篇文章很有帮助:http://www.scala-archive.org/scala-Double-td1939353.html

并最终将代码更改为:

clust_recs.map(rec => rec.getPremium().doubleValue()).stats()

输出:

res28: org.apache.spark.util.StatCounter = (count: 1000000, mean: 170.636, stdev: 28.13, max: 2180.000000, min: 0.000000)

【讨论】:

以上是关于运行“stats()”的 Spark 错误:找不到参数 num 的隐式值:Numeric [Double]的主要内容,如果未能解决你的问题,请参考以下文章

mysql错误:找不到表“mysql”。“innodb_table_stats”

SparkContext 错误 - 找不到文件 /tmp/spark-events 不存在

sbt打包Scala写的Spark程序,打包正常,提交运行时提示找不到对应的类

PySpark - 系统找不到指定的路径

找不到php dll模块

Spark sql 在yarn-cluster模式下找不到表