【问题标题】:Round timestamp to nearest 30 second将时间戳舍入到最接近的 30 秒
【发布时间】:2018-10-25 23:46:39
【问题描述】:

我在 DF 中有一个列,它包含格式为 (yyyy-mm-dd HH:mm:ss) 的 timestamp。我需要将timestamp 舍入到最接近的 30 秒。

old column                   desired column
2016-02-09 19:31:02          2016-02-09 19:31:00  
2016-02-09 19:31:35          2016-02-09 19:31:30
2016-02-09 19:31:52          2016-02-09 19:32:00
2016-02-09 19:31:28          2016-02-09 19:31:30

是否可以在 Pyspark 中做到这一点?

【问题讨论】:

    标签: python pyspark timestamp unix-timestamp


    【解决方案1】:

    如果您使用的是 spark 版本 1.5+,则可以使用 pyspark.sql.functions.second() 从时间戳列中获取秒数。

    import pyspark.sql.functions as f
    df.withColumn("second", f.second("old_timestamp")).show()
    #+-------------------+------+
    #|      old_timestamp|second|
    #+-------------------+------+
    #|2016-02-09 19:31:02|     2|
    #|2016-02-09 19:31:35|    35|
    #|2016-02-09 19:31:52|    52|
    #|2016-02-09 19:31:28|    28|
    #+-------------------+------+
    

    一旦你有了秒部分,你就可以取这个数字,除以 30,四舍五入,然后乘以 30 得到“新”秒。

    df.withColumn("second", f.second("old_timestamp"))\
        .withColumn("new_second", f.round(f.col("second")/30)*30)\
        .show()
    #+-------------------+------+----------+
    #|      old_timestamp|second|new_second|
    #+-------------------+------+----------+
    #|2016-02-09 19:31:02|     2|       0.0|
    #|2016-02-09 19:31:35|    35|      30.0|
    #|2016-02-09 19:31:52|    52|      60.0|
    #|2016-02-09 19:31:28|    28|      30.0|
    #+-------------------+------+----------+
    

    从“新”秒开始,我们可以计算以秒为单位的偏移量,当添加到原始时间戳时,将产生所需的“四舍五入”时间戳。

    df.withColumn("second", f.second("old_timestamp"))\
        .withColumn("new_second", f.round(f.col("second")/30)*30)\
        .withColumn("add_seconds", f.col("new_second") - f.col("second"))\
        .show()
    #+-------------------+------+----------+-----------+
    #|      old_timestamp|second|new_second|add_seconds|
    #+-------------------+------+----------+-----------+
    #|2016-02-09 19:31:02|     2|       0.0|       -2.0|
    #|2016-02-09 19:31:35|    35|      30.0|       -5.0|
    #|2016-02-09 19:31:52|    52|      60.0|        8.0|
    #|2016-02-09 19:31:28|    28|      30.0|        2.0|
    #+-------------------+------+----------+-----------+
    

    如我们所见,此列中的负数意味着必须向下舍入原始时间。正数将增加时间。

    为了将此时间添加到原始时间戳,首先使用pyspark.sql.functions.unix_timestamp() 将其转换为unix 时间戳。添加后,使用pyspark.sql.functions.from_unixtime() 将结果转换回时间戳。

    把这一切放在一起(浓缩中间步骤):

    df.withColumn(
            "add_seconds",
            (f.round(f.second("old_timestamp")/30)*30) - f.second("old_timestamp")
        )\
        .withColumn(
            "new_timestamp",
            f.from_unixtime(f.unix_timestamp("old_timestamp") + f.col("add_seconds"))
        )\
        .drop("add_seconds")\
        .show()
    #+-------------------+-------------------+
    #|      old_timestamp|      new_timestamp|
    #+-------------------+-------------------+
    #|2016-02-09 19:31:02|2016-02-09 19:31:00|
    #|2016-02-09 19:31:35|2016-02-09 19:31:30|
    #|2016-02-09 19:31:52|2016-02-09 19:32:00|
    #|2016-02-09 19:31:28|2016-02-09 19:31:30|
    #+-------------------+-------------------+
    

    【讨论】:

    • 感谢您的努力!我以不同的方式做到了。
    • 我将时间转换为以(秒)为单位的纪元,然后将结果数字四舍五入为 30,然后将新纪元转换为人类可读的日期
    • 这很有帮助,谢谢!我稍微修改了一下,以四舍五入到最接近的 30 分钟间隔,效果很好。
    猜你喜欢
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 2017-12-02
    • 2018-05-27
    • 2014-12-12
    • 2014-04-07
    相关资源
    最近更新 更多