从Spark写入时避免丢失分区数据的数据类型

问题描述:

我有一个如下所示的数据框。从Spark写入时避免丢失分区数据的数据类型

itemName, itemCategory 
Name1, C0 
Name2, C1 
Name3, C0 

我想保存这个数据帧作为划分拼花文件:

df.write.mode("overwrite").partitionBy("itemCategory").parquet(path) 

对于这个数据帧,当我读回数据,这将有字符串的数据类型itemCategory

但有时,我有其他租户的数据框如下。

itemName, itemCategory 
Name1, 0 
Name2, 1 
Name3, 0 

在这种情况下,被写为分区,当读回后,所得到的数据帧将具有int对于的itemCategory的数据类型。

Parquet文件具有描述数据类型的元数据。我如何指定分区的数据类型,以便将其读回为String而不是Int?

+0

它是正确的假设,当你在阅读“在其他时间” dataframes,它是越来越为CSV或需要的类型的文件格式读入,以推断? – ayplam

+0

不,这些文件采用实木复合格式,因此除分区键之外,不会传送数据类型。 – suriyanto

由于您的partitionBy itemCategory,此数据将存储在文件结构中,而不是存储在实际的csv文件中。我的猜测是Spark根据值推断数据类型,如果所有值都是整数,那么列类型将为int。

一个简单的解决办法是在读取数据后,列转换为StringType

import spark.implicits._ 
df.withColumn("itemCategory", $"itemCategory".cast(StringType)) 

另一种办法是复制列本身。然后其中一列将用于分区,并因此保存在文件结构中。但是,其他复制的列通常会保存在实木复合地板文件中。为了使重复的简单的使用:

df.withColumn("itemCategoryCopy", $"itemCategory") 
+0

感谢您的回答。不幸的是,我简化了问题中的问题。我有一个通用的Parquet阅读器,它通过请求的分区将文件读入数据框,因此必须引入这个特定的逻辑是相当大的挑战。 – suriyanto

+0

@suriyanto我看到了,我添加了一个替代解决方案,可能可以帮助你,虽然解决方案不是很优雅。 – Shaido