Pyspark 字符串到十进制转换以及精度和格式,如 Java 十进制格式化程序

Posted

技术标签:

【中文标题】Pyspark 字符串到十进制转换以及精度和格式,如 Java 十进制格式化程序【英文标题】:Pyspark String to Decimal Conversion along with precision and format like Java decimal formatter 【发布时间】:2020-05-22 16:33:30 【问题描述】:

我正在尝试将字符串转换为十进制。 有时我可能会收到如下十进制数据 1234.6789-(最后是-) 在java中,我可以指定如下格式来解析上面,DecimalFormat dfmt = new DecimalFormat("0000.0000;0000.0000-") 这样我得到的十进制值为-1234.6789

我们在 Python 或 Pyspark 中是否有类似的功能

我已经创建了 UDF

def getDecimalVal(myString):
    return Decimal(myString)
ConvertToDec = udf(getDecimalVal, DecimalType(4))

我在下面的代码中调用它

Employee = Row("firstName", "lastName", "email", "salary","salaryday")
employee1 = Employee('steve', 'mill', 'bash@elean.co', "0012.7590","2020-04-30")
employee2 = Employee( 'jack','neil', 'daniel@ssl.edu', "0013.2461","2020-04-30" )
employees=[employee1,employee2]
dframe = spark.createDataFrame(employees)
dframe=dframe.withColumn('decimalval',ConvertToDec(col('salary'))) 
dframe.show()

下面是输出

+---------+--------+--------------+---------+----------+---------+----------+
|firstName|lastName|         email|   salary| salaryday|finalname|decimalval|
+---------+--------+--------------+---------+----------+---------+----------+
|      len|armbrust| bash@learn.co|  0012.75|2020-04-30|      len|        13|
|      dem|    meng|daniel@uda.edu|0013.2461|2020-04-30|      dem|        13|
+---------+--------+--------------+---------+----------+---------+----------+

我有以下问题 1) 十进制值而不是 12.759013.2461 正在四舍五入到 13 2) 如果我将 UDF 中的岁差更改为 DecimalType(4,4) 我得到以下错误

 Py4JJavaError: An error occurred while calling o2598.showString.
java.lang.IllegalArgumentException: requirement failed: Decimal precision 6 exceeds max precision 4

我如何保持精度以及如何保持精度

【问题讨论】:

【参考方案1】:

您可以先将regexp_reaplace 移动到前面的- 符号,然后将cast 移动到DecimalType。这样,您就不必使用 UDF。这样的事情应该可以工作:

from pyspark.sql.functions import regexp_replace
...
dframe = dframe.withColumn(
    'decimalval',
    regexp_replace('salary', r'([0-9\.]+)\-', '-$1').cast("DECIMAL(8,4)"))

请注意,如果十进制数中有 8 位数字,则应使用 DecimalType(8, 4) 而不是 DecimalType(4, 4)。来自 pyspark 文档here

precision – the maximum total number of digits (default: 10)

scale – the number of digits on right side of dot. (default: 0)

【讨论】:

谢谢,你的解决方案有效,但有时我可能会得到十进制值,如 0909.8978 我没有 - 最后返回 null 我希望值为 0909.8978 regexp_replace 在没有- 的情况下也应该可以工作。但是,您还需要确保案例能够正常工作。如果它不能被转换为小数,你最终会得到空值。 由于数据有空间,我最终得到了空值。谢谢

以上是关于Pyspark 字符串到十进制转换以及精度和格式,如 Java 十进制格式化程序的主要内容,如果未能解决你的问题,请参考以下文章

Inferschema 检测列作为字符串而不是来自 pyspark 中镶木地板的双精度

格式化字符串:标准数字格式

使用最少十进制位数格式化双精度类型

负十进制数/字符串到 IEEE 单精度格式

BigInteger大精度整数

C# 将字符串转换为双精度/十进制并返回字符串,保留尾随零,为千位添加逗号