Как преобразовать тип Any List в тип Double (Scala) - PullRequest
1 голос
/ 24 апреля 2019

Я новичок в Scala, и я хотел бы понять некоторые базовые вещи.

Прежде всего, мне нужно вычислить среднее определенного столбца DataFrame и использовать результат как переменную двойного типа,

После некоторых исследований в Интернете мне удалось вычислить среднее значение и одновременно передать его в Тип списка Любой с помощью следующей команды:

val avgX_List = mainDataFrame.groupBy().agg(mean("_c1")).collect().map(_(0)).toList

где " _c1 " - это второй столбец моего кадра данных .Эта строка кода возвращает список с типом List [Any] .

Чтобы передать результат в переменную, я использовал следующую команду:

var avgX = avgX_List(0)

, надеясь, что var avgX автоматически наберет тип double, но этого явно не произошло.

Итак, теперь давайте начнем вопросы:

  1. Что означает map(_(0)) do?Я знаю базовое определение преобразования map(), но не могу найти объяснения с этим точным аргументом

  2. Я знаю, что с помощью метода .toList в конце командымоим результатом будет список типа Any.Есть ли способ, которым я мог бы изменить это в список, который содержит элементы типа Double?Или даже преобразовать этот

  3. Как вы думаете, было бы гораздо более уместным передать столбец моего Dataframe в List [Double], а затем вычислить среднее его элементов?

  4. Является ли решение, которое я показал выше, с какой-либо точки зрения, правильным, основываясь на моей проблеме?Я знаю, что «это работает» отличается от «правильного решения»?

Подводя итог, мне нужно вычислить среднее значение для определенного столбца Dataframe и получить результат в видепеременная двойного типа.

Обратите внимание: я - грек, и иногда мне трудно понять какой-то английский код "сленг".

Ответы [ 2 ]

4 голосов
/ 24 апреля 2019

map(_(0)) является ярлыком для map( (r: Row) => r(0) ), который, в свою очередь, является ярлыком для map( (r: Row) => r.apply(0) ).Метод apply возвращает Any, и поэтому вы теряете правильный тип.Попробуйте вместо этого использовать map(_.getAs[Double](0)) или map(_.getDouble(0)).

Сбор всех записей столбца и последующее вычисление среднего значения будут крайне контрпродуктивными, поскольку вам придется отправлять огромные объемы данных на главный узел, изатем выполните все вычисления на этом единственном центральном узлеЭто было бы полной противоположностью того, для чего подходит Spark.

Вам также не нужен collect(...).toList, потому что вы можете напрямую получить доступ к 0-й записи (не имеет значения, получаете ли вы ее отArray или List).Так как вы в любом случае сводите все в один Row, вы можете полностью избавиться от шага map, переупорядочив методы немного:

val avgX = mainDataFrame.groupBy().agg(mean("_c1")).collect()(0).getDouble(0)

Его можно записать еще короче, используя first метод:

val avgX = mainDataFrame.groupBy().agg(mean("_c1")).first().getDouble(0)
1 голос
/ 24 апреля 2019
#Any dataType in Scala can't be directly converted to Double.
#Use toString & then toDouble on final captured result.

#Eg-

#scala> x
#res22: Any = 1.0

#scala> x.toString.toDouble
#res23: Double = 1.0

#Note- Instead of using map().toList() directly use (0)(0) to get the final value from your resultset.


#TestSample(Scala)-

val wa = Array("one","two","two")
val wrdd = sc.parallelize(wa,3).map(x=>(x,1))
val wdf = wrdd.toDF("col1","col2")
val x = wdf.groupBy().agg(mean("col2")).collect()(0)(0).toString.toDouble

#O/p-
#scala> val x = wdf.groupBy().agg(mean("col2")).collect()(0)(0).toString.toDouble
#x: Double = 1.0

...