несоответствие типов искры scala с zipwithIndex в групповом ключе - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь проверить groupByKey, чтобы найти n-й наивысший балл предмета

мои данные выглядят так

scala> a
res176: org.apache.spark.rdd.RDD[(String, String)] = MapPartitionsRDD[263] at map at <console>:51

scala> a.take(10).foreach{println}
(data science,DN,US,28,98,SMITH,data science)
(maths,DN,US,28,92,SMITH,maths)
(chemistry,DN,US,28,94,SMITH,chemistry)
(physics,DN,US,28,88,SMITH,physics)
(data science,DN,UK,25,93,JOHN,data science)
(maths,DN,UK,25,91,JOHN,maths)
(chemistry,DN,UK,25,95,JOHN,chemistry)
(physics,DN,UK,25,90,JOHN,physics)
(data science,DN,CA,29,67,MARK,data science)
(maths,DN,CA,29,68,MARK,maths)

scala> 

, поэтому для первой строки "наука о данных", поскольку строка является ключевойи "DN, US, 28,98, SMITH, data science" - это значение в виде строки

. Теперь я хочу найти 2-ю группу с наибольшим использованием по

scala> a.groupByKey().flatMap(rec=>{ val max = rec._2.toList.map(x=>x.split(',')(3).toFloat).distinct.sortBy(x=>(-x)).zipWithIndex.filter(x=>x._2==2).toMap.keys
     | rec._2.toList.filter{x=>x.split(',')(3).toFloat==max}
     | }).take(15).foreach{println}

scala> 

Я ничего здесь не получаю

если я запускаю этот жестко запрограммированный код, я получаю значение

scala> a.groupByKey().flatMap(rec=>{ val max = "98"
     | rec._2.toList.sortBy(x=>(-x.split(',')(3).toFloat)).takeWhile(rec=> max.contains(rec.split(',')(3)))}).take(15).foreach{println}
DN,IND,26,98,XMAN,maths
DPS,US,28,98,XOMAN,chemistry
DN,US,28,98,SMITH,data science

, и это дает мне значение

scala> a.groupByKey().flatMap(rec=>{ rec._2.toList.map(x=>x.split(',')(3).toFloat).distinct.sortBy(x=>(-x)).zipWithIndex.filter(x=>x._2==2).map(_._1)}).take(15).foreach{println}
94.0
92.0
95.0
93.0

, более сложный код дает мне вывод

scala> a.groupByKey().flatMap(rec=>{ val max = rec._2.toList.map(x=>x.split(',')(3).toFloat).distinct.sortBy(x=>(-x)).take(1)
     | rec._2.toList.sortBy(x=>(-x.split(',')(3).toFloat)).takeWhile(rec=> max.contains(rec.split(',')(3).toFloat))}).take(15).foreach{println}
DN,IND,26,98,XMAN,maths
DPS,UK,25,96,SOMK,physics
DPS,US,28,98,XOMAN,chemistry
DN,US,28,98,SMITH,data science

похоже, что при использовании zipwithindex наблюдается некоторое несоответствие типов данных.Может ли кто-нибудь помочь мне здесь

1 Ответ

0 голосов
/ 02 февраля 2019

Существует несоответствие типов из-за .toMap.keys.В результате val max имеет тип Iterable [Float], потому что метод keys возвращает Iterable [A].

В качестве решения будет добавлено head в конце вычисления max:

  val max = rec._2.toList
    .map(x => x.split(',')(3).toFloat)
    .distinct
    .sortBy(x => (-x))
    .zipWithIndex
    .filter(x => x._2 == 2)
    .toMap
    .keys
    .head

По сути, head вернет значение типа Float,Тогда этот код должен как минимум сравнивать равные типы x.split(',')(3).toFloat == max.

Хотя вызов head не является безопасным методом.Может выдать исключение, если в вашем случае функция filter может вернуть пустой список.Тогда будет выдано такое исключение:

java.util.NoSuchElementException: next on empty iterator

Как только это сработает для конкретного образца данных, вы можете подумать о том, чтобы реорганизовать этот код для работы с Set, может быть.Вместо head сделайте .keys.toSet и сравните, как вы делали для других примеров, используя max.contains(rec.split(',')(3))

...