从 Spark 写入镶木地板时如何处理空值

Posted

技术标签:

【中文标题】从 Spark 写入镶木地板时如何处理空值【英文标题】:How to handle null values when writing to parquet from Spark 【发布时间】:2018-10-14 02:24:46 【问题描述】:

直到最近 parquet 不支持 null 值 - 一个值得怀疑的前提。事实上,最近的一个版本终于添加了这种支持:

https://github.com/apache/parquet-format/blob/master/LogicalTypes.md

但是,spark 支持新的 parquet 功能还需要很长时间 - 如果有的话。这是关联的 (closed - will not fix) JIRA:

https://issues.apache.org/jira/browse/SPARK-10943

那么在将dataframe's 写成parquet 时,今天,人们对空列值做了什么?我只能想到 非常 丑陋可怕的 hack,比如编写空字符串和 .. 好吧 .. 我 知道如何处理数值来指示 null - 简短放入一些哨兵值并让我的代码检查它(这很不方便且容易出错)。

【问题讨论】:

【参考方案1】:

我为此编写了一个 PySpark 解决方案(df 是一个包含NullType 列的数据框):

# get dataframe schema
my_schema = list(df.schema)

null_cols = []

# iterate over schema list to filter for NullType columns
for st in my_schema:
    if str(st.dataType) == 'NullType':
        null_cols.append(st)

# cast null type columns to string (or whatever you'd like)
for ncol in null_cols:
    mycolname = str(ncol.name)
    df = df \
        .withColumn(mycolname, df[mycolname].cast('string'))

【讨论】:

这真的很有帮助 这个解决方案可以扩展为处理嵌套的 NullType 列购买将行更改为if 'NullType' in str(st.dataType):【参考方案2】:

你误解了SPARK-10943。 Spark 确实支持将 null 值写入数字列。

问题是null 本身根本没有类型信息

scala> spark.sql("SELECT null as comments").printSchema
root
 |-- comments: null (nullable = true)

根据comment by Michael Armbrust,您所要做的就是演员:

scala> spark.sql("""SELECT CAST(null as DOUBLE) AS comments""").printSchema
root
|-- comments: double (nullable = true)

结果可以安全地写入 Parquet。

【讨论】:

如果你使用 sql 类似这样的工作:create table my_table as select distinct colx, coly, cast(null as string) colz from foo where lower(bar) like '%bat%' 是否有可能以某种方式强制转换 StructType 的字段?我的意思是,有一个类型是结构的列,其中有一个类型被推断为 NullType 的字段。也可以投吗?

以上是关于从 Spark 写入镶木地板时如何处理空值的主要内容,如果未能解决你的问题,请参考以下文章

将镶木地板文件读入数据框时如何为文件夹结构指定架构[重复]

在 Spark 2.0 中从 AVRO 写入镶木地板时出现 NullPointerException

spark sql 无法在 S3 中查询镶木地板分区

Spark保存(写入)镶木地板只有一个文件

如何在镶木地板文件中使用 K-means

镶木地板写入期间的 Spark ClosedChannelException 异常