PySpark数据帧将异常字符串格式转换为Timestamp

时间:2016-08-22 20:47:06

标签: apache-spark dataframe pyspark apache-spark-sql timestamp

我通过Spark 1.5.0使用PySpark。 对于datetime值,我在列的行中有一个不常见的String格式。它看起来像这样:

Row[(daytetime='2016_08_21 11_31_08')]

有没有办法将这种非正统的yyyy_mm_dd hh_mm_dd格式转换为时间戳?

最终会出现的问题
df = df.withColumn("date_time",df.daytetime.astype('Timestamp'))

我原以为像regexp_replace这样的Spark SQL函数可以工作,但我当然需要替换 日期一半_ - 在时间部分_:

我以为我可以使用substring将列拆分为2,并从时间结束向后计数。然后做' regexp_replace'分开,然后连接。但这似乎很多操作?有更简单的方法吗?

4 个答案:

答案 0 :(得分:35)

Spark> = 2.2

from pyspark.sql.functions import to_timestamp

(sc
    .parallelize([Row(dt='2016_08_21 11_31_08')])
    .toDF()
    .withColumn("parsed", to_timestamp("dt", "yyyy_MM_dd hh_mm_ss"))
    .show(1, False))

## +-------------------+-------------------+
## |dt                 |parsed             |
## +-------------------+-------------------+
## |2016_08_21 11_31_08|2016-08-21 11:31:08|
## +-------------------+-------------------+

Spark< 2.2

unix_timestamp无法处理:

from pyspark.sql import Row
from pyspark.sql.functions import unix_timestamp

(sc
    .parallelize([Row(dt='2016_08_21 11_31_08')])
    .toDF()
    .withColumn("parsed", unix_timestamp("dt", "yyyy_MM_dd hh_mm_ss")
    .cast("double")
    .cast("timestamp"))
    .show(1, False))

## +-------------------+---------------------+
## |dt                 |parsed               |
## +-------------------+---------------------+
## |2016_08_21 11_31_08|2016-08-21 11:31:08.0|
## +-------------------+---------------------+

在这两种情况下,格式字符串应与Java SimpleDateFormat兼容。

答案 1 :(得分:3)

zero323的答案回答了这个问题,但是我想补充一点,如果您的datetime字符串具有标准格式,则应该可以将其直接转换为时间戳类型:

df.withColumn('datetime', col('datetime_str').cast('timestamp'))

它具有处理毫秒的优势,而 unix_timestamp 仅具有秒精度( to_timestamp 也可以毫秒级,但需要Spark> = 2.2,如zero323所述)。我在Spark 2.3.0上使用以下格式对其进行了测试:'2016-07-13 14:33:53.979'(以毫秒为单位,但没有它们也可以使用)。

答案 2 :(得分:1)

我添加了更多来自 Florent F's answer 的代码行,以便更好地理解和在本地机器上运行代码段:

import os, pdb, sys
import pyspark
from pyspark.sql import SparkSession
from pyspark.sql import Row
from pyspark.sql.types import StructType, ArrayType  
from pyspark.sql.types import StringType
from pyspark.sql.functions import col

sc = pyspark.SparkContext('local[*]')
spark = SparkSession.builder.getOrCreate()

# preparing some example data - df1 with String type and df2 with Timestamp type
df1 = sc.parallelize([{"key":"a", "date":"2016-02-01"}, 
    {"key":"b", "date":"2016-02-02"}]).toDF()
df1.show()

df2 = df1.withColumn('datetime', col('date').cast("timestamp"))
df2.show()

答案 3 :(得分:0)

我完全同意选择的答案,但是我想将格式设置为“ yyyy_MM_dd HH_mm_ss”,以避免像“ 2019_01_27 16_00_00”这样的时间戳出现问题->注意小时> 12