2016-01-23 77 views
1
case class Varnish(ID: String, varnish_latency: Float) 


val seq = sc.sequenceFile[LongWritable, BytesWritable](logfile_path) 
val usableRDD = seq.map({case (_, v : BytesWritable) => Text.decode(v.getBytes)}) 
        .map(_.split(" ")) 
        .map(p => Varnish(p(11), p(8).toFloat)) 
        .toDF() 
usableRDD.registerTempTable("Varnish") 
sqlContext.sql("SELECT * from Varnish LIMIT 5").collect().foreach(println) // works fine 
val countResult = sqlContext.sql("SELECT COUNT(*) FROM Varnish").collect() // throws Err 
val cnt2 = countResult.head.getLong(0) 

16/01/23 2点56分18秒sparkDriver-akka.actor.default-dispatcher- 20 INFO RemoteActorRefProvider $ RemotingTerminator:关闭远程守护进程。
16/01/23 02:56:18线程3 INFO ApplicationMaster:取消注册失败的ApplicationMaster(诊断消息:用户类抛出异常:org.apache.spark.SparkException:由于阶段失败导致作业中止:阶段中的任务57 1.0失败4次,最近失败:
在阶段1.0(TID 89,10.1.201.14)中丢失的任务57.3:java.lang.NumberFormatException:对于输入字符串:“nan”
at sun.misc.FloatingDecimal.readJavaFormatString FloatingDecimal.java:1250)java.lang.NumberFormatException:对于输入字符串: “南” 上SELECT COUNT(*)在表上

回答

3

例外似乎是相当不言自明的。有些你传递的价值观包含nan字符串,它不被解释为有效Float表示:

scala> "nan".toFloat 
java.lang.NumberFormatException: For input string: "nan" 
... 

只要数据不是来自已经已经验证(如RDBMS或平面文件)源代码的话不应该盲目地相信它有一个正确的格式。您可以修改您的代码通过选择正确处理这种情况和其他恶意条目:

import scala.util.Try 

case class Varnish(ID: String, varnish_latency: Option[Float]) 

... 
    .map(p => Varnish(p(11), Try(p(8).toFloat).toOption)) 

降案例类和处理这个使用SQL:

... 
    .map(p => Varnish(p(11), p(8))) 
    .toDF("ID", "varnish_latency") 
    .withColumn("varnish_latency", $"varnish_latency".cast("double")) 

或预验证你打电话.toFloat前删除格式错误的条目。

前两个选项会将Nones转换为nulls。由于它不是语义上的精确(原始非数字与缺失值)并导致信息丢失,因此您可能更愿意明确处理“nan”情况。例如,它可以通过更换"nan""NaN"(正确的表示)调用toFloat或模式匹配之前完成:

p(8) match { 
    case "nan" => Float.NaN 
    case s => s.toFloat 
} 
+0

这就是我一直在寻找解决方案。谢谢。对不起,我是scala的新手,我如何继续进行scala大小写匹配。我想忽略/放置其中p(8)==“nan”的列。 p(8)匹配{case}“nan”=>? case s => s.toFloat } – user1579557

+0

您可以通过不同的方法来处理这个问题,但'flatMap' +空'Seq'将是我个人的选择。 – zero323

相关问题