PySpark:在数据帧中将时间戳转换为整数时出现不一致

时间:2017-09-08 18:48:12

标签: python datetime dataframe pyspark bigdata

我有一个粗略结构的数据框,如下所示:

+-------------------------+-------------------------+--------+
| timestamp               | adj_timestamp           | values |
+-------------------------+-------------------------+--------+
| 2017-05-31 15:30:48.000 | 2017-05-31 11:30:00.000 | 0      |
+-------------------------+-------------------------+--------+
| 2017-05-31 15:31:45.000 | 2017-05-31 11:30:00.000 | 0      |
+-------------------------+-------------------------+--------+
| 2017-05-31 15:32:49.000 | 2017-05-31 11:30:00.000 | 0      |
...

我正在尝试将转换函数应用于两个时间列,以使用time包将它们转换为整数表示形式。我的用户定义函数以及它如何应用于上面的数据框:

def timeConverter(timestamp):
    time_tuple = time.strptime(timestamp, "%Y-%m-%d %H:%M:%S.000")
    timevalue = time.mktime(time_tuple)
    return timevalue

def convertDateColumn(Data):
    timeUDF = udf(timeConverter,FloatType())
    finalData = Data.withColumn('adj_timestamp', timeUDF('adj_timestamp'))

    return finalData

例如,adj_timestamp列中的第一个条目变为: 1496244608

通过datetime.fromtimestamp转换回来会导致:2017-05-31 15:30:08

这与我开始时的价值不同......对于发生了什么感到好奇!

编辑:由于我的行数比显示的数据多得多,是否有可能异步处理数据,因此生成的数据帧与输入的数据顺序不一样?

1 个答案:

答案 0 :(得分:3)

对于udf,我不太清楚为什么它不起作用。将Python函数转换为UDF时可能是浮点操作问题。了解如何在下面使用整数输出。或者,您可以使用名为unix_timestamp的Spark函数来解析,该函数允许您转换时间戳。我举一个例子如下。希望它有所帮助。

在这里,我根据您显示的示例创建Spark数据框,

import pandas as pd

df = pd.DataFrame([
    ['2017-05-31 15:30:48.000', '2017-05-31 11:30:00.000', 0], 
    ['2017-05-31 15:31:45.000', '2017-05-31 11:30:00.000', 0],
    ['2017-05-31 15:32:49.000', '2017-05-31 11:30:00.000', 0]], 
    columns=['timestamp', 'adj_timestamp', 'values'])
df = spark.createDataFrame(df)

使用Spark函数解决

fn.unix_timestamp应用于专栏timestamp

import pyspark.sql.functions as fn
from pyspark.sql.types import *
df.select(fn.unix_timestamp(fn.col('timestamp'), format='yyyy-MM-dd HH:mm:ss.000').alias('unix_timestamp')).show()

对于第一列,输出看起来像这样

+--------------+
|unix_timestamp|
+--------------+
|    1496259048|
|    1496259105|
|    1496259169|
+--------------+

您可以使用datetime库将其恢复为时间戳:

import datetime
datetime.datetime.fromtimestamp(1496259048) # output as datetime(2017, 5, 31, 15, 30, 48)

通过转换为interger而不是float

来解决
import datetime
import time

def timeConverter(timestamp):
    time_tuple = datetime.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.000").timetuple()
    timevalue = int(time.mktime(time_tuple)) # convert to int here
    return timevalue

time_udf = fn.udf(timeConverter, IntegerType()) # output interger

df.select(time_udf(fn.col('timestamp'))) 

在这里,我们将获得与使用[1496259048, 1496259105, 1496259169]相同的时间戳unix_timestamp