Искра: округлено до десятичного в наборе данных - PullRequest
0 голосов
/ 07 мая 2018

У меня есть набор данных, как показано ниже, где в случае DataFrame я могу легко округлить до 2 десятичных знаков но мне просто интересно, есть ли более простой способ сделать то же самое при использовании набора типизированных данных.

Вот мой фрагмент кода:

import org.apache.spark.sql.{DataFrame, Dataset}
import org.apache.spark.sql.expressions.scalalang.typed.{sum => typedSum}
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types.{DecimalType}

case class Record(BOOK: String,ID: String,CCY: String,AMT: Double)  

def getDouble(num: Double) = {BigDecimal(num).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble}    

val ds = Seq(
("ALBIBC","1950363","USD",2339055.7945),
("ALBIBC","1950363","USD",78264623778.813345),
("ALBIBC","1950363","USD",45439055.222),
("ALBIBC","1950363","EUR",746754759055.343),
("ALBIBC","1950363","EUR",343439055.88780),
).toDS("BOOK","ID","CCY","AMT")

Dataframe way производит следующий вывод:

val df: DataFrame = data.groupBy('BOOK,'ID,'CCY).agg(sum('AMT).cast(DecimalType(38,2)).as("Balance"))
df.show()

+------+-------+---+---------------+
|  BOOK|     ID|CCY|        Balance|
+------+-------+---+---------------+
|ALBIBC|1950363|USD| 78312401889.83|
|ALBIBC|1950363|EUR|747098198111.23|
+------+-------+---+---------------+

Как бы я округлил баланс до 2 знаков после запятой в случае набора данных?

val sumBalance = typedSum[Record](_.AMT).as[Double].name("Balance")
val ds = data.groupByKey(thor => (thor.BOOK, thor.ID, thor.CCY)).agg(sumBalance.name("Balance"))
               .map{case(key,value) => (key._1,key._2,key._3,getDouble(value))}
ds.show()   

+------+-------+---+------------------+
|    _1|     _2| _3|                _4|
+------+-------+---+------------------+
|ALBIBC|1950363|USD| 7.831240188983E10|
|ALBIBC|1950363|EUR|7.4709819811123E11|
+------+-------+---+------------------+

Я могу пойти по пути данных, но мне просто интересно узнать, используя наборы данных? Любой совет по этому вопросу, пожалуйста.

Спасибо

1 Ответ

0 голосов
/ 07 мая 2018

Ваша ошибка - преобразование обратно в Double. Представление с плавающей точкой не может представлять все возможные числа .

Переопределить (и, вероятно, переименовать) вашу функцию:

def getDouble(num: Double) = BigDecimal(num).setScale(
  2, BigDecimal.RoundingMode.HALF_UP
)

Пример:

Seq(7.831240188983E10, 7.4709819811123E11).toDS.map(getDouble).show

// +---------------+           
// |          value|
// +---------------+
// | 78312401889.83|
// |747098198111.23|
// +---------------+
...