gpt4 book ai didi

apache-spark - 将 CSV 读入具有时间戳和日期类型的 Spark Dataframe

转载 作者:行者123 更新时间:2023-12-01 22:19:56 28 4
gpt4 key购买 nike

这是带有 Spark 1.6 的 CDH。

我正在尝试将此假设的 CSV 导入到 apache Spark DataFrame 中:

$ hadoop fs -cat test.csv
a,b,c,2016-09-09,a,2016-11-11 09:09:09.0,a
a,b,c,2016-09-10,a,2016-11-11 09:09:10.0,a

我使用databricks-csv jar。

val textData = sqlContext.read
.format("com.databricks.spark.csv")
.option("header", "false")
.option("delimiter", ",")
.option("dateFormat", "yyyy-MM-dd HH:mm:ss")
.option("inferSchema", "true")
.option("nullValue", "null")
.load("test.csv")

我使用 inferSchema 为生成的 DataFrame 制作架构。 printSchema() 函数为我提供了上述代码的以下输出:

scala> textData.printSchema()
root
|-- C0: string (nullable = true)
|-- C1: string (nullable = true)
|-- C2: string (nullable = true)
|-- C3: string (nullable = true)
|-- C4: string (nullable = true)
|-- C5: timestamp (nullable = true)
|-- C6: string (nullable = true)

scala> textData.show()
+---+---+---+----------+---+--------------------+---+
| C0| C1| C2| C3| C4| C5| C6|
+---+---+---+----------+---+--------------------+---+
| a| b| c|2016-09-09| a|2016-11-11 09:09:...| a|
| a| b| c|2016-09-10| a|2016-11-11 09:09:...| a|
+---+---+---+----------+---+--------------------+---+

C3 列具有String 类型。我希望 C3 具有 日期 类型。为了得到它的日期类型,我尝试了以下代码。

val textData = sqlContext.read.format("com.databricks.spark.csv")
.option("header", "false")
.option("delimiter", ",")
.option("dateFormat", "yyyy-MM-dd")
.option("inferSchema", "true")
.option("nullValue", "null")
.load("test.csv")

scala> textData.printSchema
root
|-- C0: string (nullable = true)
|-- C1: string (nullable = true)
|-- C2: string (nullable = true)
|-- C3: timestamp (nullable = true)
|-- C4: string (nullable = true)
|-- C5: timestamp (nullable = true)
|-- C6: string (nullable = true)

scala> textData.show()
+---+---+---+--------------------+---+--------------------+---+
| C0| C1| C2| C3| C4| C5| C6|
+---+---+---+--------------------+---+--------------------+---+
| a| b| c|2016-09-09 00:00:...| a|2016-11-11 00:00:...| a|
| a| b| c|2016-09-10 00:00:...| a|2016-11-11 00:00:...| a|
+---+---+---+--------------------+---+--------------------+---+

此代码与第一个 block 之间的唯一区别是 dateFormat 选项行(我使用 "yyyy-MM-dd" 而不是 "yyyy- MM-dd HH:mm:ss")。现在我将 C3 和 C5 都作为时间戳(C3 仍然不是日期)。但对于 C5,HH::mm:ss 部分将被忽略并在数据中显示为零。

理想情况下,我希望 C3 为日期类型,C5 为时间戳类型,并且不忽略其 HH:mm:ss 部分。我现在的解决方案看起来像这样。我通过从数据库并行提取数据来制作 csv。我确保将所有日期提取为时间戳(不理想)。因此,测试 csv 现在看起来像这样:

$ hadoop fs -cat new-test.csv
a,b,c,2016-09-09 00:00:00,a,2016-11-11 09:09:09.0,a
a,b,c,2016-09-10 00:00:00,a,2016-11-11 09:09:10.0,a

这是我最终的工作代码:

val textData = sqlContext.read.format("com.databricks.spark.csv")
.option("header", "false")
.option("delimiter", ",")
.option("dateFormat", "yyyy-MM-dd HH:mm:ss")
.schema(finalSchema)
.option("nullValue", "null")
.load("new-test.csv")

在这里,我在 dateFormat 中使用完整的时间戳格式(“yyyy-MM-dd HH:mm:ss”)。我手动创建 FinalSchema 实例,其中 c3 是日期,C5 是时间戳类型(Spark sql 类型)。我使用 schema() 函数应用这些模式。输出如下所示:

scala> finalSchema
res4: org.apache.spark.sql.types.StructType = StructType(StructField(C0,StringType,true), StructField(C1,StringType,true), StructField(C2,StringType,true), StructField(C3,DateType,true), StructField(C4,StringType,true), StructField(C5,TimestampType,true), StructField(C6,StringType,true))

scala> textData.printSchema()
root
|-- C0: string (nullable = true)
|-- C1: string (nullable = true)
|-- C2: string (nullable = true)
|-- C3: date (nullable = true)
|-- C4: string (nullable = true)
|-- C5: timestamp (nullable = true)
|-- C6: string (nullable = true)


scala> textData.show()
+---+---+---+----------+---+--------------------+---+
| C0| C1| C2| C3| C4| C5| C6|
+---+---+---+----------+---+--------------------+---+
| a| b| c|2016-09-09| a|2016-11-11 09:09:...| a|
| a| b| c|2016-09-10| a|2016-11-11 09:09:...| a|
+---+---+---+----------+---+--------------------+---+

是否有更简单或开箱即用的方法来解析 csv 文件(将日期和时间戳类型放入 Spark 数据帧中?

相关链接:
http://spark.apache.org/docs/latest/sql-programming-guide.html#manually-specifying-options
https://github.com/databricks/spark-csv

最佳答案

对于非平凡情况使用推断选项,它可能不会返回预期结果。正如您在 InferSchema.scala 中看到的那样:

if (field == null || field.isEmpty || field == nullValue) {
typeSoFar
} else {
typeSoFar match {
case NullType => tryParseInteger(field)
case IntegerType => tryParseInteger(field)
case LongType => tryParseLong(field)
case DoubleType => tryParseDouble(field)
case TimestampType => tryParseTimestamp(field)
case BooleanType => tryParseBoolean(field)
case StringType => StringType
case other: DataType =>
throw new UnsupportedOperationException(s"Unexpected data type $other")

它只会尝试将每列与时间戳类型匹配,而不是日期类型,因此这种情况的“开箱即用的解决方案”是不可能的。但根据我的经验,“更简单”的解决方案是直接使用 needed type 定义架构。 ,它将避免将推断选项设置为仅匹配评估的 RDD 而不是整个数据的类型。您的最终架构是一个有效的解决方案。

关于apache-spark - 将 CSV 读入具有时间戳和日期类型的 Spark Dataframe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40878243/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com