【问题标题】:Replace a column with a calcutated column using the same name in spark SQL在 spark SQL 中将列替换为使用相同名称的计算列
【发布时间】:2019-05-11 05:53:53
【问题描述】:

我从我的数据湖中读取文件并将它们加载到数据框中 由于kafka中的转换问题(here),加载的数据有一些与源数据库中不同类型的字段

所以,我使用错误的数据类型(二进制文件)从 S3 加载数据,然后使用 UDF 函数将每一列转换为另一列

然后,我重命名新列以替换旧列,以在源数据库和目标数据库中保持相同的结构

步骤:

之前:

myTable
|
+-- myField1 (binary)
+-- myField2 (binary)
+-- myField3 (binary)

中间状态 1(使用 UDF 函数强制转换):

myTable
|
+-- myField1 (binary)
+-- myField1_new (numeric)
+-- myField2 (binary)
+-- myField2_new (numeric)
+-- myField3 (binary)
+-- myField3_new (numeric)

中间状态 2(删除旧列):

myTable
|
+-- myField1_new (numeric)
+-- myField2_new (numeric)
+-- myField3_new (numeric)

最终状态(重命名计算列):

myTable
|
+-- myField1 (numeric)
+-- myField1 (numeric)
+-- myField1 (numeric)

这是我使用的语法:

spark.sql('select *,
            MyUDF(myfield1) myfield1_new,
            MyUDF(myfield2) myfield2_new,
            MyUDF(myfield3) myfield3_new
            from my_table')
.drop('myfield1').withColumnRenamed('myfield1_new', 'myfield1')
.drop('myfield2').withColumnRenamed('myfield2_new', 'myfield2')
.drop('myfield3').withColumnRenamed('myfield3_new', 'myfield3')
.show(1, False)

我的问题是这个过程真的很慢,因为在实际生产表中要计算 439 个字段(439 !!!)

有没有更快的方法?即时重命名或其他什么?

感谢您的帮助

【问题讨论】:

  • 你试过data = data.withColumn("myfield1", yourUdf('myfield1'))吗?

标签: pyspark apache-spark-sql pipeline


【解决方案1】:

我看到了previous 这个问题的帖子。

扩展那个 as,假设你有 df as

+--------------------+
|             myfield|
+--------------------+
|[00, 8F, 2B, 9C, 80]|
|    [52, F4, 92, 80]|
+--------------------+

EDIT:由于myfield列的格式为bytearray(b'\x00'),转换方式如下(@Ftagn指出)。否则,如果是字符串列表,则使用commented return

def func(val):
    return int.from_bytes(val, byteorder='big', signed=False) / 1000000
    # return int("".join(val), 16)/1000000
func_udf = udf(lambda x: func(x), FloatType())

要创建输出,请使用

df = df.withColumn("myfield1", func_udf("myfield"))

这会产生,

+--------------------+--------+
|             myfield|myfield1|
+--------------------+--------+
|[00, 8F, 2B, 9C, 80]|  2402.0|
|    [52, F4, 92, 80]| 1391.76|
+--------------------+--------+

如果你使用,

df = df.withColumn("myfield", func_udf("myfield"))

你明白了,

+-------+
|myfield|
+-------+
| 2402.0|
|1391.76|
+-------+

【讨论】:

  • 感谢您的技巧!请注意,它适用于return int.from_bytes(val, byteorder='big', signed=False) / 1000000 不适用于return int("".join(val), 16)/1000000 为我引发异常` File "", line 2, in func TypeError: sequence item 0: expected str instance, int found`
  • 啊..你能说type(df1.select('myfield').collect()[0][0])的输出是什么
  • 字节数组(b'\x00')
猜你喜欢
  • 1970-01-01
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多