/ / java.lang.NumberFormatException: Dla ciągu wejściowego podczas transformacji RDD - scala, apache-spark

java.lang.NumberFormatException: Dla ciągu wejściowego podczas przekształcania RDD - scala, apache-spark

RDD

scala> val rdd = sc.parallelize(List(("A",1), ("A",2), ("B",1), ("A",3), ("B",2)))
rdd: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[806] at parallelize at <console>:30

Transformacja

scala> rdd.map(r => r.toString.split(",")).map(r => (r(0), r(1).toInt)).collect()

Otrzymuję następujący błąd podczas przekształcania tego RDD przy użyciu mapy:

17/08/12 12:22:18 ERROR executor.Executor: Exception in task 2.0 in stage 161.0 (TID 7031)
java.lang.NumberFormatException: For input string: "1)"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)

Odpowiedzi:

0 dla odpowiedzi № 1

Problem polega na tym, że próbujesz przekonwertować 1) na liczbę, gdy dodatkowy nawias powoduje wyjątek NumberFormatException.

Spróbuj się zmienić r.toString.split(",").map(r => (r(0), r(1).toInt)).collect() po prostu r.map(r => (r(0), r(1).toInt)).collect() i zobacz, czy to naprawi.


0 dla odpowiedzi nr 2

To dlatego, że nie powinieneś używać toString :) Z twojego kodu:

rdd.map(r => r.toString.split(","))

Tutaj krotki (A, B) są odwzorowane na ciąg (A, B), a następnie podzielisz go na (A i B). Co jest dość zabawne, rdd szybko już pisze RDD[(String, Int)] :)

Zamiast tego nie powinieneś używać toString i tej funkcji mapy. Możesz także:

rdd.map(r=> r.toString.replaceAll("(", "").replaceAll(")", "").split(","))

Więc zastąpisz () pustymi ciągami z wejściowego ciągu


0 dla odpowiedzi № 3

Twój ostatni krok sugeruje, że tworzysz RDD[Tuple2(String, Int)]

Ale twój pierwszy krok już został stworzony RDD[tuple2(String, Int)] który jest tuple i w scala uzyskanie elementów tuple jest zrobione przez._1 , ._2 itp.

scala> val rdd = sc.parallelize(List(("A",1), ("A",2), ("B",1), ("A",3), ("B",2)))
rdd: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[0] at parallelize at <console>:25

Więc myślę, że nie potrzebujesz .toInt w drugim parametrze, ponieważ jest już an Int. Tak więc wykonywanie poniższych czynności powinno działać

scala> rdd.map(r => (r._1, r._2)).collect
res0: Array[(String, Int)] = Array((A,1), (A,2), (B,1), (A,3), (B,2))

Jeśli nadal dołączasz .toInt, nadal będzie działać

scala> rdd.map(r => (r._1, r._2.toInt)).collect
res1: Array[(String, Int)] = Array((A,1), (A,2), (B,1), (A,3), (B,2))

Tak więc konwersja tuple2 na String i podzielenie łańcucha w celu przekształcenia go w pierwotną formę byłoby, jak sądzę, wyłącznie do celów testowych.

Jeśli to jest powód, to kiedy tuple2 jest konwertowane na String przez .toString ( i ) w zestawie są również wsporniki, które należy usunąć. Tak więc właściwym sposobem na zrobienie drugiego kroku byłoby

scala> rdd.map(r => r.toString().replaceAll("[()]", "").split(",")).map(r => (r(0), r(1).toInt)).collect
res2: Array[(String, Int)] = Array((A,1), (A,2), (B,1), (A,3), (B,2))