如何强制inferSchema将CSV中的整数视为日期(使用“dateFormat”选项)?

8

我使用的是Spark 2.2.0版本。

我正在按照以下方式读取csv文件:

val dataFrame = spark.read.option("inferSchema", "true")
                          .option("header", true)
                          .option("dateFormat", "yyyyMMdd")
                          .csv(pathToCSVFile)

该文件中有一个日期列,所有记录在该特定列中的值都等于 20171001

问题是Spark推断该列的类型为integer而不是date。当我删除"inferSchema"选项时,该列的类型为string

该文件中没有null值,也没有格式错误的行。

这个问题的原因/解决方案是什么?


1
你可以尝试禁用 ("inferSchema", "true") 并提供自定义模式来读取 csv 文件。 - Avishek Bhattacharya
1
我可以,但我猜“dateFormat”选项是为了避免你所建议的做法,对吧? - Rami
1
如果我的记忆还好的话,它需要用双引号进行转义。 - eliasah
2个回答

11
如果我的理解是正确的,代码暗示了以下类型推断的顺序(先检查第一个类型):
- NullType - IntegerType - LongType - DecimalType - DoubleType - TimestampType - BooleanType - StringType 因此,我认为问题在于,在考虑到TimestampType之前,20171001已经匹配了IntegerType(使用 timestampFormat而不是 dateFormat选项)。
解决方案之一是定义模式,并将其与DataFrameReaderschema运算符一起使用,或者让Spark SQL推断模式并使用cast运算符。
如果字段数量不是很多,我会选择前者。

4
在这种情况下,由于格式的模糊性,您不能仅依赖模式推断。
由于输入可以被解析为IntegerType(或任何更高精度的数字格式)以及TimestamType,前者具有更高的优先级(在内部Spark尝试IntegerType->LongType->DecimaType->DoubleType->TimestampType),推断机制永远不会达到TimestampType情况。
具体来说,启用模式推断后,Spark 将调用tryParseInteger,正确解析输入并停止。后续调用将匹配第二个案例并在同一tryParseInteger调用处结束。

“推断机制永远不会到达TimestampType情况。”我认为这并不成立,考虑到https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVInferSchema.scala?utf8=%E2%9C%93#L86-L98。 - Jacek Laskowski
它有效。您链接的模式匹配中从句的顺序无关紧要。 - zero323

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