在PySpark中使用微秒级时间戳

时间:2019-01-17 09:14:51

标签: python scala apache-spark pyspark apache-spark-sql

我有一个带有以下时间格式20190111-08:15:45.275753的pyspark数据帧。我想将其转换为时间戳格式,并保持微秒级的粒度。但是,似乎很难保持微秒,因为pyspark中的所有时间转换都产生秒吗?

您对如何做到这一点有任何了解吗?请注意,将其转换为pandas等将不起作用,因为数据集非常庞大,因此我需要一种有效的方法来执行此操作。我在下面如何执行此操作的示例

time_df = spark.createDataFrame([('20150408-01:12:04.275753',)], ['dt'])
res = time_df.withColumn("time",  unix_timestamp(col("dt"), \
format='yyyyMMdd-HH:mm:ss.000').alias("time"))
res.show(5, False)

2 个答案:

答案 0 :(得分:0)

通常时间戳的粒度以秒为单位,因此我认为没有直接的方法可以保持毫秒的粒度。

在pyspark中,有一个unix_timestamp函数:

  

unix_timestamp(timestamp=None, format='yyyy-MM-dd HH:mm:ss')

     

使用给定模式转换时间字符串(默认为'yyyy-MM-dd HH:mm:ss')       使用默认时区和默认值设置为Unix时间戳(以秒为单位)       语言环境,如果失败,则返回null。

if `timestamp` is None, then it returns current timestamp.

>>> spark.conf.set("spark.sql.session.timeZone", "America/Los_Angeles")
>>> time_df = spark.createDataFrame([('2015-04-08',)], ['dt'])
>>> time_df.select(unix_timestamp('dt', 'yyyy-MM-dd').alias('unix_time')).collect()
[Row(unix_time=1428476400)]
>>> spark.conf.unset("spark.sql.session.timeZone")

一个用法示例:

import pyspark.sql.functions as F
res = df.withColumn(colName,  F.unix_timestamp(F.col(colName), \
    format='yyyy-MM-dd HH:mm:ss.000').alias(colName) )

您可能要做的是拆分日期字符串(str.rsplit('.', 1)),使数据框中的毫秒数分开(例如,通过创建另一列)。

编辑

在您的示例中,问题在于时间是字符串类型的。首先,您需要将其转换为timestamp类型:可以通过以下方式完成:

res = time_df.withColumn("new_col", to_timestamp("dt", "yyyyMMdd-hh:mm:ss"))

然后您可以使用unix_timestap

res2 = res.withColumn("time",  F.unix_timestamp(F.col("parsed"), format='yyyyMMdd-hh:mm:ss.000').alias("time"))

最后创建一个以毫秒为单位的列:

res3 = res2.withColumn("ms", F.split(res2['dt'], '[.]').getItem(1))

答案 1 :(得分:0)

我已经在pyspark中使用to_utc_timestamp函数找到了解决此问题的方法,但是尽管似乎可以处理大约1亿行数据,但不能完全确定这是否是最有效的方法。如果您的时间戳字符串如下所示,则可以避免使用regex_replace- 1997-02-28 10:30:40.897748

 from pyspark.sql.functions import regexp_replace, to_utc_timestamp

 df = spark.createDataFrame([('19970228-10:30:40.897748',)], ['new_t'])
 df = df.withColumn('t', regexp_replace('new_t', '^(.{4})(.{2})(.{2})-', '$1-$2-$3 '))
 df = df.withColumn("time", to_utc_timestamp(df.t, "UTC").alias('t'))
 df.show(5,False)
 print(df.dtypes)