Как я могу отключить округление в Spark?

#python #dataframe #apache-spark #pyspark #rounding

Вопрос:

Например, у меня есть фрейм данных, и я делаю это:

 df = dataframe.withColumn("test", lit(0.4219759403))
 

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

Когда я выполняю приведение к десятичному типу с .cast(DataTypes.createDecimalType(20,4) помощью или даже с помощью функции округления, это число округляется до 0.4220 .

Единственный способ , который я нашел, чтобы сделать это без округления, — это применить функцию format_number() , но эта функция дает мне строку, и когда я ее приведу string to DecimalType(20,4) , фреймворк снова округлит число до 0.4220 .

Мне нужно преобразовать это число в enter code here десятичный тип(20,4) без округления, и я ожидаю увидеть 0.4219 .

Как я могу это сделать?

Ответ №1:

Если у вас есть числа с более чем 1 цифрой перед десятичной запятой, substr это не соответствует. Вместо этого вы можете использовать регулярное выражение, чтобы всегда извлекать первые 4 десятичных знака (если они есть).
Вы можете сделать это с помощью regexp_extract

 df = dataframe.withColumn('rounded', F.regexp_extract(F.col('test'), 'd .d{0,4}', 0))
 

Пример

 import pyspark.sql.functions as F

dataframe = spark.createDataFrame([
    (0.4219759403, ),
    (0.4, ),
    (1.0, ),
    (0.5431293, ),
    (123.769859, )
], ['test'])
df = dataframe.withColumn('rounded', F.regexp_extract(F.col('test'), 'd .d{0,4}', 0))
df.show()

 ------------ -------- 
|        test| rounded|
 ------------ -------- 
|0.4219759403|  0.4219|
|         0.4|     0.4|
|         1.0|     1.0|
|   0.5431293|  0.5431|
|  123.769859|123.7698|
 ------------ -------- 
 

Ответ №2:

Привет, добро пожаловать в stackoverflow,
пожалуйста, в следующий раз попробуйте привести воспроизводимый пример с кодом, который вы пробовали, в любом случае это работает для меня:

 from pyspark.sql.types import DecimalType
df = spark.createDataFrame([
    (1, "a"),
    (2, "b"),
    (3, "c"),
], ["ID", "Text"])

df = df.withColumn("test", lit(0.4219759403))
df = df.withColumn("test_string", F.substring(df["test"].cast("string"), 0, 6))
df = df.withColumn("test_string_decimaltype", df["test_string"].cast(DecimalType(20,4)))
df.show()
df.printSchema()

 --- ---- ------------ ----------- ----------------------- 
| ID|Text|        test|test_string|test_string_decimaltype|
 --- ---- ------------ ----------- ----------------------- 
|  1|   a|0.4219759403|     0.4219|                 0.4219|
|  2|   b|0.4219759403|     0.4219|                 0.4219|
|  3|   c|0.4219759403|     0.4219|                 0.4219|
 --- ---- ------------ ----------- ----------------------- 

root
 |-- ID: long (nullable = true)
 |-- Text: string (nullable = true)
 |-- test: double (nullable = false)
 |-- test_string: string (nullable = false)
 |-- test_string_decimaltype: decimal(20,4) (nullable = true) 
 

Конечно, если вы хотите, вы можете перезаписать один и тот же столбец, поставив всегда «тест», я выбираю разные имена, чтобы вы могли видеть шаги.