将浮点列添加到时间戳类型列(秒+毫秒)

Posted

技术标签:

【中文标题】将浮点列添加到时间戳类型列(秒+毫秒)【英文标题】:Adding float column to TimestampType column (seconds+miliseconds) 【发布时间】:2021-07-07 17:41:47 【问题描述】:

我正在尝试将浮点列添加到 pyspark 中的 TimestampType 列,但似乎没有办法在保持小数秒的同时做到这一点。 float_seconds 示例为 19.702300786972046,时间戳示例为 2021-06-17 04:31:32.48761

我想要什么:

calculated_df = beginning_df.withColumn("calculated_column", float_seconds_col + TimestampType_col)

我尝试了以下方法,但都没有完全解决问题:

#method 1 添加单个时间,但不能用于将整列添加到时间戳列。

calculated_df = beginning_df.withColumn("calculated_column",col("TimestampType_col") + F.expr('INTERVAL 19.702300786 seconds'))

#method 2 将 float 列转换为 unixtime,但去掉小数(这很重要)

timestamp_seconds = beginning_df.select(from_unixtime("float_seconds"))

Image of the two columns in question

【问题讨论】:

如果以下答案有帮助,请告诉我 根据您的示例,预期的结果是什么。是2021-06-17 04:31:52.189911 【参考方案1】:

您可以使用 UDF 来实现它,如下所示:

from datetime import datetime, timedelta

from pyspark.sql import SparkSession
from pyspark.sql.functions import col, udf
from pyspark.sql.types import StructType, StructField, FloatType, TimestampType

spark = SparkSession \
    .builder \
    .appName("StructuredStreamTesting") \
    .getOrCreate()
schema = (StructType([
    StructField('dt', TimestampType(), nullable=True),
    StructField('sec', FloatType(), nullable=True),
]))

item1 = 
    "dt": datetime.fromtimestamp(1611859271.516),
    "sec": 19.702300786,

item2 = 
    "dt": datetime.fromtimestamp(1611859271.517),
    "sec": 19.702300787,


item3 = 
    "dt": datetime.fromtimestamp(1611859271.518),
    "sec": 19.702300788,


df = spark.createDataFrame([item1, item2, item3], schema=schema)

df.printSchema()


@udf(returnType=TimestampType())
def add_time(dt, sec):
    return dt + timedelta(seconds=sec)


df = df.withColumn("new_dt", add_time(col("dt"), col("sec")))
df.printSchema()
df.show(truncate=False)

【讨论】:

谢谢!这是否可以扩展到非常大的数据集? IMO,这应该是可扩展的,你也可以运行分析。【参考方案2】:

时间戳数据类型支持纳秒(最大 9 位精度)。您的 float_seconds_col 的精度 > 9 位(在您的示例中为 15,它是飞秒),无论如何转换为 Timestamp 都会丢失。

普通香草蜂巢:

select 
      timestamp(cast(concat(cast(unix_timestamp(TimestampType_col) as string), --seconds
                            '.', 
                            regexp_extract(TimestampType_col,'\\.(\\d+)$')) --fractional
                     as decimal (30, 15) 
                   ) + float_seconds_col --round this value to nanos to get better timestamp conversion (round(float_seconds_col,9))
               ) as result --max precision is 9 (nanoseconds)
       
from
(
select 19.702300786972046                     float_seconds_col,
       timestamp('2021-06-17 04:31:32.48761') TimestampType_col
) s

结果:

2021-06-17 04:31:52.189910786

【讨论】:

@elfriend 如果可行,请接受/投票

以上是关于将浮点列添加到时间戳类型列(秒+毫秒)的主要内容,如果未能解决你的问题,请参考以下文章

js 怎么取到时间戳里面的月份?

Python Pandas:每周列(int)到时间戳列转换(以周为单位)

将日期添加到时间戳

BigQuery 字符串到时间戳,在源中保留时区

MySql,将日期和时间列组合成时间戳

将五个小时添加到时间戳字段