spark mapPartitionRDD无法打印值

时间:2016-03-20 23:35:44

标签: python scala apache-spark

我正在使用Spark Book跟踪机器学习并尝试将python代码转换为scala代码并使用Beaker笔记本共享变量,以便将值传递给python以使用matplotlib进行绘图,如本书所述。到目前为止,我已经能够转换大部分代码,但我在使用try-catch数据集进行数据清理的u.item转换时遇到了一些问题。下面的代码以无限循环结束,没有明确的错误是什么。

val movieData = sc.textFile("/Users/minHenry/workspace/ml-100k/u.item")
val movieDataSplit = movieData.first()

val numMovies = movieData.count()

def convertYear(x:String):Int = x.takeRight(4) match {
         case x => x.takeRight(4).toInt
         case _ => 1900
    }

val movieFields = movieData.map(lines => lines.split('|'))
print(movieData.first())
val years1 = movieFields.map(fields => fields(2))

val years = movieFields.map(fields => fields(2).map(x=>convertYear(x.toString())))
val filteredYears = years.filter(x => x!=1900)
years.take(2).foreach(println)

我怀疑我的问题与我的模式匹配有关,但我不确定它的错误。我认为takeRight()有效,因为它并没有抱怨这个函数被应用的类型。

更新

根据迄今为止提供的答案,我已根据以下建议更新了代码:

import scala.util.Try
val movieData = sc.textFile("/Users/minHenry/workspace/ml-100k/u.item")

def convertYear(x:String):Int = Try(x.toInt).getOrElse(1900)
val movieFields = movieData.map(lines => lines.split('|'))

val preYears = movieFields.map(fields => fields(2))
val years = preYears.map(x => x.takeRight(4))//.map(x=>convertYear(x))
println("=======> years")
years.take(2).foreach(println) //--output = 1995/n1995
println("=======> filteredYears")
val filteredYears = years.filter(x => x!=1900)

filteredYears.take(2).foreach(println)
//val movieAges = filteredYears.map(yr => (1998-yr)).countByValue() 

我在map之后注释了takeRight(4)因为它比放置x=>convertYear(x.takeRight(4))更容易评论,并且应该产生相同的输出。当我应用这个convertYear()函数时,我仍然以无限循环结束。值显示在所显示的几个打印语句中。问题是如果我无法删除无法轻易转换为Int的数据点,那么我无法在最后一行运行countByValue()函数。

以下是我的公共烧杯笔记本的链接以获取更多背景信息: https://pub.beakernotebook.com/#/publications/56eed31d-85ad-4728-a45d-14b3b08d673f

1 个答案:

答案 0 :(得分:1)

  1. movieData: RDD[String]
  2. movieFields: RDD[Array[String]]
  3. years1: RDD[String]
  4. val years = movieFields.map(fields => fields(2).map(x=>convertYear(x.toString()))) - fields(2)String,因此xChar,因为String被视为Seq[Char]convertYear(x: String)的所有输入只有一个字母字符串。
  5. 您的错误是类型不兼容隐藏(convertYear(x.toString()))。它是警钟。始终在scala中使用类型系统,不要隐藏toString()isInstanceOf或其他内容的问题。然后编译器在运行之前显示错误。

    P.S。

    1. takeRight的第二次通话毫无用处。
    2. def convertYear(x:String):Int = x.takeRight(4) match { case x => x.takeRight(4).toInt case _ => 1900 }
    3. 模式匹配是关于检查类型或条件(使用if语句)。你的第一个部分功能没有检查任何东西。所有输入都转到x.takeRight(4).toInt。此外,没有针对toInt例外的辩护。 请改用def convertYear(x: String): Int = Try(x.toInt).getOrElse(1900)

      <强>更新

      scala> import scala.util.Try
      import scala.util.Try
      
      scala> def convertYear(x:String):Int = Try(x.toInt).getOrElse(1900)
      convertYear: (x: String)Int
      
      scala> List("sdsdf", "1989", "2009", "1945", "asdf", "455")
      res0: List[String] = List(sdsdf, 1989, 2009, 1945, asdf, 455)
      
      scala> res0.map(convertYear)
      res1: List[Int] = List(1900, 1989, 2009, 1945, 1900, 455)
      

      与RDD完全相同,因为它是一个类似于List的函子。

      val filteredYears = years.filter(x => x!=1900)无法按预期工作。 x是String而不是Int。 Scala没有隐式转换类型进行比较。所以你总是得到true