Pyspark 字符串到十进制的转换以及精度和格式,如 Java 十进制格式化程序
Pyspark String to Decimal Conversion along with precision and format like Java decimal formatter
我正在尝试将字符串转换为十进制。
有时我可能会收到如下的十进制数据
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.7590 和 13.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
如何保持精度以及如何保持精度
您可以regexp_reaplace
先将-
标志移到前面,然后cast
移到DecimalType
。这样您就不必使用 UDF。这样的事情应该有效:
from pyspark.sql.functions import regexp_replace
...
dframe = dframe.withColumn(
'decimalval',
regexp_replace('salary', r'([0-9\.]+)\-', '-').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)
我正在尝试将字符串转换为十进制。
有时我可能会收到如下的十进制数据
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.7590 和 13.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
如何保持精度以及如何保持精度
您可以regexp_reaplace
先将-
标志移到前面,然后cast
移到DecimalType
。这样您就不必使用 UDF。这样的事情应该有效:
from pyspark.sql.functions import regexp_replace
...
dframe = dframe.withColumn(
'decimalval',
regexp_replace('salary', r'([0-9\.]+)\-', '-').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)