pyspark 如何修复非法Parquet类型:INT64(TIMESTAMP_MICROS)错误

utugiqy6  于 2023-11-16  发布在  Spark
关注(0)|答案(3)|浏览(179)

我在PySpark中使用了一个sqlContext.read.parquet函数来每天读取parquet文件。数据有一个timestamp列。他们将时间戳字段从2019-08-26T00:00:13.600+0000更改为2019-08-26T00:00:13.600Z。它在数据块中读起来很好。但是当我试图通过一个spark cluster读取它时,它给出了一个Illegal Parquet type: INT64 (TIMESTAMP_MICROS)错误。我如何使用read.parquet函数本身读取这个新列呢?
目前我用途:from_unixtime(unix_timestamp(ts,"yyyy-MM-dd HH:mm:ss.SSS"),"yyyy-MM-dd")作为ts将2019-08-26T00:00:13.600+0000转换为2019-08-26
如何将2019-08-26T00:00:13.600Z转换为2019-08-26

snz8szmq

snz8szmq1#

这里是scala版本

import spark.implicits._
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types._

val df2 = Seq(("a3fac", "2019-08-26T00:00:13.600Z")).toDF("id", "eventTime")
val df3= df2.withColumn("eventTime1", to_date(unix_timestamp($"eventTime", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").cast(TimestampType)))

df3.show(false)
+-----+------------------------+----------+
|id   |eventTime               |eventTime1|
+-----+------------------------+----------+
|a3fac|2019-08-26T00:00:13.600Z|2019-08-26|
+-----+------------------------+----------+

字符串
下面一行是将时区日期转换为日期
第一个月

pyspark版本:

>>> from pyspark.sql.functions import col, to_date,unix_timestamp
>>> df2=spark.createDataFrame([("a3fac", "2019-08-26T00:00:13.600Z")], ['id', 'eventTime'])
>>> df3=df2.withColumn("eventTime1", to_date(unix_timestamp(col("eventTime"), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").cast('timestamp')))
>>> df3.show()
+-----+--------------------+----------+
|   id|           eventTime|eventTime1|
+-----+--------------------+----------+
|a3fac|2019-08-26T00:00:...|2019-08-26|
+-----+--------------------+----------+

brgchamk

brgchamk2#

您可以从功能模块使用to_date API

import pyspark.sql.functions as f

dfl2 = spark.createDataFrame([(1, "2019-08-26T00:00:13.600Z"),]).toDF('col1', 'ts')

dfl2.show(1, False)
+----+------------------------+
|col1|ts                      |
+----+------------------------+
|1   |2019-08-26T00:00:13.600Z|
+----+------------------------+

dfl2.withColumn('date',f.to_date('ts', "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")).show(1, False)

+----+------------------------+----------+
|col1|ts                      |date      |
+----+------------------------+----------+
|1   |2019-08-26T00:00:13.600Z|2019-08-26|
+----+------------------------+----------+

dfl2.withColumn('date',f.to_date('ts', "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")).printSchema()
root
 |-- col1: long (nullable = true)
 |-- ts: string (nullable = true)
 |-- date: date (nullable = true)

字符串

6mw9ycah

6mw9ycah3#

这可能是由于您的数据被一个系统写入到parquet,而您试图从另一个系统读取parquet。这两个系统使用不同版本的Parquet。
我也有类似的问题。在我的例子中,我在Python中准备了带有时间戳列的数据,并使用pandas.to_parquet保存。后来我试图在EMR上读取Pyspark中的parquet,得到了错误:

org.apache.spark.sql.AnalysisException: Illegal Parquet type: INT64 (TIMESTAMP(NANOS,false))

字符串
经过一番搜索,发现这是由Pandas和Pyspark可以处理的不同时间戳分辨率引起的。我的数据集有几个时间戳列。在Pandas中,时间戳以纳秒分辨率表示。然而,Pyspark使用的某些Parquet阅读器可能仅支持以毫秒(“ms”)或微秒(“us”)分辨率存储的时间戳。有关更多讨论,请参阅https://arrow.apache.org/docs/python/parquet.html#storing-timestamps。
因此,当我保存Pandas框架和时间戳列时,我显式地强制时间戳列为微秒分辨率。我必须在Python中为每个分区执行强制转换。

相关问题