#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)
Конечно, если вы хотите, вы можете перезаписать один и тот же столбец, поставив всегда «тест», я выбираю разные имена, чтобы вы могли видеть шаги.