从Spark写入parquet时如何处理null值

32

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

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

然而,要让spark支持新的parquet特性还需要很长时间-如果有可能的话。这里是相关的(已关闭 - 不会修复)JIRA:

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

那么在写出dataframeparquet时,人们如今对于空列值的处理方式是什么呢?我只能想到非常丑陋可怕的hack方法,例如写入空字符串和...好吧...我不知道该如何处理数值以指示null - 除了放置一些标志性值并让我的代码进行检查(这很不方便且容易出错)。

2个回答

39
你误解了SPARK-10943。Spark支持将null值写入数字列。
问题在于null本身不包含任何类型信息。
scala> spark.sql("SELECT null as comments").printSchema
root
 |-- comments: null (nullable = true)

根据Michael Armbrustcomment,你所要做的就是进行强制类型转换:
scala> spark.sql("""SELECT CAST(null as DOUBLE) AS comments""").printSchema
root
|-- comments: double (nullable = true)

结果可以安全地写入Parquet。


1
如果您正在使用 SQL,可以像这样创建表:create table my_table as select distinct colx, coly, cast(null as string) colz from foo where lower(bar) like '%bat%'。 - John
有没有办法对StructType的字段进行转换?我的意思是,有一列的类型是一个结构体,其中有一个字段的类型被推断为NullType。是否也可以将其转换? - Roman Puchkovskiy

14

我为此编写了一个 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'))

3
此解决方案可通过更改以下行以处理嵌套的NullType列:if 'NullType' in str(st.dataType): - miked
如果NullType列是空数组怎么办? - Omega

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接