将空数据帧保存到镶木地板会导致错误 - Spark 2.4.4
Saving empty dataframe to parquet results in error - Spark 2.4.4
我有一段代码,最后我将数据帧写入 parquet 文件。
逻辑是数据帧有时可能为空,因此出现以下错误。
df.write.format("parquet").mode("overwrite").save(somePath)
org.apache.spark.sql.AnalysisException: Parquet data source does not support null data type.;
当我打印 "df" 的架构时,我得到了下面的结果。
df.schema
res2: org.apache.spark.sql.types.StructType =
StructType(
StructField(rpt_date_id,IntegerType,true),
StructField(rpt_hour_no,ShortType,true),
StructField(kpi_id,IntegerType,false),
StructField(kpi_scnr_cd,StringType,false),
StructField(channel_x_id,IntegerType,false),
StructField(brand_id,ShortType,true),
StructField(kpi_value,FloatType,false),
StructField(src_lst_updt_dt,NullType,true),
StructField(etl_insrt_dt,DateType,false),
StructField(etl_updt_dt,DateType,false)
)
是否有一种解决方法可以只写入带有架构的空文件,或者在空文件时根本不写入文件?
谢谢
'还是空的时候根本不写文件?'检查df是否不为空然后只写它。
if (!df.isEmpty)
df.write.format("parquet").mode("overwrite").save("somePath")
您收到的错误与您的数据框为空这一事实无关。我没有看到保存空数据框的意义,但如果你愿意,你可以这样做。如果你不相信我,试试这个:
val schema = StructType(
Array(
StructField("col1",StringType,true),
StructField("col2",StringType,false)
)
)
spark.createDataFrame(spark.sparkContext.emptyRDD[Row], schema)
.write
.format("parquet")
.save("/tmp/test_empty_df")
您收到该错误是因为您的其中一列是 NullType 并且抛出的异常表明 "Parquet data source does not support null data type"
我不能确定为什么你有一个 Null 类型的列,但这通常发生在你从源读取数据并让 spark 推断架构时。如果该源中有一个空列,spark 将无法推断模式并将其设置为空类型。
如果是这种情况,我的建议是您在读取时指定架构。
如果不是这种情况,一个可能的解决方案是将 NullType 的所有列转换为 parquet 兼容类型(如 StringType)。以下是如何操作的示例:
//df is a dataframe with a column of NullType
val df = Seq(("abc",null)).toDF("col1", "col2")
df.printSchema
root
|-- col1: string (nullable = true)
|-- col2: null (nullable = true)
//fold left to cast all NullType to StringType
val df1 = df.columns.foldLeft(df){
(acc,cur) => {
if(df.schema(cur).dataType == NullType)
acc.withColumn(cur, col(cur).cast(StringType))
else
acc
}
}
df1.printSchema
root
|-- col1: string (nullable = true)
|-- col2: string (nullable = true)
希望对您有所帮助
我有一段代码,最后我将数据帧写入 parquet 文件。
逻辑是数据帧有时可能为空,因此出现以下错误。
df.write.format("parquet").mode("overwrite").save(somePath)
org.apache.spark.sql.AnalysisException: Parquet data source does not support null data type.;
当我打印 "df" 的架构时,我得到了下面的结果。
df.schema
res2: org.apache.spark.sql.types.StructType =
StructType(
StructField(rpt_date_id,IntegerType,true),
StructField(rpt_hour_no,ShortType,true),
StructField(kpi_id,IntegerType,false),
StructField(kpi_scnr_cd,StringType,false),
StructField(channel_x_id,IntegerType,false),
StructField(brand_id,ShortType,true),
StructField(kpi_value,FloatType,false),
StructField(src_lst_updt_dt,NullType,true),
StructField(etl_insrt_dt,DateType,false),
StructField(etl_updt_dt,DateType,false)
)
是否有一种解决方法可以只写入带有架构的空文件,或者在空文件时根本不写入文件? 谢谢
'还是空的时候根本不写文件?'检查df是否不为空然后只写它。
if (!df.isEmpty)
df.write.format("parquet").mode("overwrite").save("somePath")
您收到的错误与您的数据框为空这一事实无关。我没有看到保存空数据框的意义,但如果你愿意,你可以这样做。如果你不相信我,试试这个:
val schema = StructType(
Array(
StructField("col1",StringType,true),
StructField("col2",StringType,false)
)
)
spark.createDataFrame(spark.sparkContext.emptyRDD[Row], schema)
.write
.format("parquet")
.save("/tmp/test_empty_df")
您收到该错误是因为您的其中一列是 NullType 并且抛出的异常表明 "Parquet data source does not support null data type"
我不能确定为什么你有一个 Null 类型的列,但这通常发生在你从源读取数据并让 spark 推断架构时。如果该源中有一个空列,spark 将无法推断模式并将其设置为空类型。
如果是这种情况,我的建议是您在读取时指定架构。
如果不是这种情况,一个可能的解决方案是将 NullType 的所有列转换为 parquet 兼容类型(如 StringType)。以下是如何操作的示例:
//df is a dataframe with a column of NullType
val df = Seq(("abc",null)).toDF("col1", "col2")
df.printSchema
root
|-- col1: string (nullable = true)
|-- col2: null (nullable = true)
//fold left to cast all NullType to StringType
val df1 = df.columns.foldLeft(df){
(acc,cur) => {
if(df.schema(cur).dataType == NullType)
acc.withColumn(cur, col(cur).cast(StringType))
else
acc
}
}
df1.printSchema
root
|-- col1: string (nullable = true)
|-- col2: string (nullable = true)
希望对您有所帮助