2016-03-20 49 views
1

我跟隨機器學習與Spark Book,並試圖將python代碼轉換爲scala代碼並使用Beaker筆記本共享變量以便將值傳遞給python以使用matplotlib繪圖,如這本書。到目前爲止,大部分代碼都能夠轉換,但我在使用u.item數據集進行數據清理時轉換try-catch時遇到了一些問題。下面的代碼以無限循環結束,沒有明確的錯誤是什麼。火花mapPartitionRDD無法打印值

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()是可行的,因爲它不會抱怨這個函數被應用到的類型。

UPDATE

我從迄今提供的答案更新的代碼如下所示,每個建議:繼takeRight(4)因爲它

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容易不是把評論x=>convertYear(x.takeRight(4))並應產生相同的輸出。當我應用這個convertYear()函數時,我仍然處於無限循環。在顯示的少量打印語句中按預期打印值。問題是如果我不能刪除不能輕易轉換爲Int的數據點,那麼我無法在最後一行運行countByValue()函數。

這裏是鏈接到我的公共燒杯筆記本更多的上下文: https://pub.beakernotebook.com/#/publications/56eed31d-85ad-4728-a45d-14b3b08d673f

+0

你的'convertYear'方法應該做什麼? –

+0

顯然有一個錯誤的數據點,所以它用1900的硬編碼值代替,然後這個值被完全刪除。通過此功能轉換的字段的格式爲「Jan-15-1988」或類似的日期值 – kinghenry14

回答

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)StringxChar,因爲String被視爲Seq[Char]。所有輸入到convertYear(x: String)只有一個字母字符串。

您的錯誤是類型不兼容性隱藏(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 }

模式匹配是有關檢查的類型或條件(用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都是一樣的,因爲它是一個仿函數的列表。

val filteredYears = years.filter(x => x!=1900)不會像你期望的那樣工作。 x是一個字符串不是整數。 Scala不會隱式轉換類型進行比較。所以你總是得到true

+0

謝謝,請參閱我的更新 – kinghenry14

+0

答案已更新。 – Zernike