pyspark 极性:将列转换为十进制

68de4m5k  于 12个月前  发布在  Spark
关注(0)|答案(2)|浏览(105)

我试图读取一个平面文件,分配列名的 Dataframe 和铸造几列根据我的要求。然而,当将列转换为Decimal时,Polars中会出现错误。我在Spark中成功地实现了同样的功能,但如果有人能指导我如何在Polars中做同样的事情,我需要帮助。
样本数据

D|120277|Patricia|167.2|26/12/1982
D|757773|Charles|167.66|08/04/2019 
D|248498|Katrina|168.68|20/11/2016 
D|325561|Christina|170.86|05/10/1998 
D|697464|Joshua|171.41|07/09/1970 
D|244750|Zachary|169.43|08/12/2014

Polar Script

import polars as pl

cols_dict = {'column_1': 'rtype', 'column_2': 'EMP_ID', 'column_3': 'EMP_NAME', 'column_4': 'SALARY', 'column_5': 'DOB'}

df = pl.read_csv(data_file, separator='|'), has_header=False)
df = df.select(pl.all().map_alias(lambda col_name: cols_dict.get(col_name)))

df = df.with_columns(
pl.col('EMP_ID').cast(pl.Decimal(scale=6, precision=0)))

它抛出异常:
exceptions.ComputeError: strict conversion from i64 to decimal[0,6] failed for value(s) \[......\]; if you were trying to cast Utf8 to temporal dtypes, consider using strptime``
Spark脚本:

rdd = sparkContext.textFile(core_data_file).filter(lambda x: x\[0\] == "D").map(
lambda x: x.split('|'))

sparkDf= rdd.toDF(schema=\["rtype"\] + list(cols_dict .values()))
sparkDf= sparkDf.withColumn(col_name, coalesce(
col(col_name).cast(DecimalType(data_length, data_scale)), lit(0)))
sarkDf.show()
+-----+------+---------+------+-------------------+
|rtype|EMP_ID|EMP_NAME |SALARY|DOB                |
+-----+------+---------+------+-------------------+
|D    |120277|Patricia |167.20|1982-12-26 00:00:00|
|D    |757773|Charles  |167.66|2019-04-08 00:00:00|
|D    |248498|Katrina  |168.68|2016-11-20 00:00:00|
|D    |325561|Christina|170.86|1998-10-05 00:00:00|
|D    |697464|Joshua   |171.41|1970-09-07 00:00:00|
|D    |244750|Zachary  |169.43|2014-12-08 00:00:00|
+-----+------+---------+------+-------------------+
vxqlmq5t

vxqlmq5t1#

在polars中,precisionscale与大多数其他类似SQL的定义相反。
在Spark代码中,DecimalType需要的是precision,然后是scale

col(col_name).cast(DecimalType(data_length, data_scale))

但是,由于极性Decimalprecision的默认值为None,而对scale没有默认值,因此顺序相反。

# A decimal[6,0]
pl.Decimal(0, 6)
pl.Decimal(scale=0, precision=6)

如果启用了十进制配置,并且正确设置了precisionscale,则强制转换将起作用。

pl.Config(activate_decimals = True)
df = df.with_columns(pl.col("EMP_ID").cast(pl.Decimal(precision=6, scale=0)))

print(df)
shape: (6, 5)
┌───────┬──────────────┬───────────┬────────┬─────────────┐
│ rtype ┆ EMP_ID       ┆ EMP_NAME  ┆ SALARY ┆ DOB         │
│ ---   ┆ ---          ┆ ---       ┆ ---    ┆ ---         │
│ str   ┆ decimal[6,0] ┆ str       ┆ f64    ┆ str         │
╞═══════╪══════════════╪═══════════╪════════╪═════════════╡
│ D     ┆ 120277       ┆ Patricia  ┆ 167.2  ┆ 26/12/1982  │
│ D     ┆ 757773       ┆ Charles   ┆ 167.66 ┆ 08/04/2019  │
│ D     ┆ 248498       ┆ Katrina   ┆ 168.68 ┆ 20/11/2016  │
│ D     ┆ 325561       ┆ Christina ┆ 170.86 ┆ 05/10/1998  │
│ D     ┆ 697464       ┆ Joshua    ┆ 171.41 ┆ 07/09/1970  │
│ D     ┆ 244750       ┆ Zachary   ┆ 169.43 ┆ 08/12/2014  │
└───────┴──────────────┴───────────┴────────┴─────────────┘
8yoxcaq7

8yoxcaq72#

我认为scaleprecision参数是无效的。scale指定小数点右侧的位数,而precision指定数字中的总位数。设置precision = 0无效。如果你想要6位小数,那么将精度重写为:

pl.col('EMP_ID').cast(pl.Decimal(scale=6, precision=None)))

我注意到pl.Decimal是一个“* 实验性的正在进行中的功能,可能无法按预期工作 *”Polars docs。另一种方法是使用pl.Float64

df = df.with_columns(pl.col('EMP_ID').cast(pl.Float64))

相关问题