PySpark:StructField(..., ..., False) 总是返回 `nullable=true` 而不是 `nullable=false`

Posted

技术标签:

【中文标题】PySpark:StructField(..., ..., False) 总是返回 `nullable=true` 而不是 `nullable=false`【英文标题】:PySpark: StructField(..., ..., False) always returns `nullable=true` instead of `nullable=false` 【发布时间】:2016-10-07 12:15:24 【问题描述】:

我是 PySpark 的新手,遇到了一个奇怪的问题。我正在尝试在加载 CSV 数据集时将某些列设置为不可为空。我可以用非常小的数据集 (test.csv) 重现我的案例:

col1,col2,col3
11,12,13
21,22,23
31,32,33
41,42,43
51,,53

第 5 行第 2 列有一个空值,我不想在我的 DF 中获取该行。我将所有字段设置为不可为空(nullable=false),但我得到了一个架构,其中所有三列都具有nullable=true。即使我将所有三列都设置为不可为空,也会发生这种情况!我正在运行 Spark 的最新可用版本 2.0.1。

代码如下:

from pyspark.sql import SparkSession
from pyspark.sql.functions import *
from pyspark.sql.types import *

spark = SparkSession \
    .builder \
    .appName("Python Spark SQL basic example") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

struct = StructType([   StructField("col1", StringType(), False), \
                        StructField("col2", StringType(), False), \
                        StructField("col3", StringType(), False) \
                    ])

df = spark.read.load("test.csv", schema=struct, format="csv", header="true")

df.printSchema() 返回:

root
 |-- col1: string (nullable = true)
 |-- col2: string (nullable = true)
 |-- col3: string (nullable = true)

df.show() 返回:

+----+----+----+
|col1|col2|col3|
+----+----+----+
|  11|  12|  13|
|  21|  22|  23|
|  31|  32|  33|
|  41|  42|  43|
|  51|null|  53|
+----+----+----+

虽然我期望这样:

root
 |-- col1: string (nullable = false)
 |-- col2: string (nullable = false)
 |-- col3: string (nullable = false)

+----+----+----+
|col1|col2|col3|
+----+----+----+
|  11|  12|  13|
|  21|  22|  23|
|  31|  32|  33|
|  41|  42|  43|
+----+----+----+

【问题讨论】:

我不认为这个问题已经完全按照issues.apache.org/jira/browse/SPARK-10848解决了 【参考方案1】:

虽然 Spark 行为(从 False 切换到 True 令人困惑,但这里并没有发生根本性的错误。nullable 参数不是约束,而是源和类型语义的反映,它启用某些类型的优化

您声明要避免数据中出现空值。为此,您应该使用na.drop 方法。

df.na.drop()

有关处理空值的其他方法,请查看DataFrameNaFunctions(使用DataFrame.na 属性公开)文档。

CSV 格式不提供任何允许您指定数据约束的工具,因此根据定义,阅读器不能假定输入不为空并且您的数据确实包含空值。

【讨论】:

这不是应该被视为错误的东西吗?你怎么能把某些东西专门设置为假,但在内部更改为真。这甚至发生在不包含任何空值开头的数据帧上。 我同意@Joop。 DataFrame 没有像我们预期的那样执行(也就是说,如果我明确要求 False,我确实想要 nullable = false)。这仍然是 Spark 中的一个问题并且尚未修复吗?我浏览了 Spark 源代码,但没有看到任何解决此问题的地方。我错过了修复吗? 这个答案不满意 我同意这个设计决定是违反直觉的。如果我在我的模式中明确设置一个字段不可为空,我希望数据符合这个模式限制,如果我在加载数据时设置选项“FAILFAST”,当非 Nuallbe 字段有时程序应该抛出异常空值。

以上是关于PySpark:StructField(..., ..., False) 总是返回 `nullable=true` 而不是 `nullable=false`的主要内容,如果未能解决你的问题,请参考以下文章

使用模式验证在 pyspark 中加载 geoJSON

如何在pyspark数据帧中过滤空值?

创建结构 PySpark 的 DataFrame

PySpark:列的绝对值。类型错误:需要浮点数

在 PySpark 中定义 JSON 模式结构的配置文件

Pyspark:如何编写复杂的 Dataframe 算法问题(带条件求和)