Pyspark - 整数表示整数到最近的四分之一小时(15分钟)

时间:2018-05-15 08:07:56

标签: apache-spark pyspark apache-spark-sql rounding

我正在Pyspark的数据框架上工作。一列由对应于时间的整数值组成:

data.select('TIME').show(4)
+------------------+
|TIME              |
+------------------+
|               925|
|              2205|
|              2205|
|              2205|
+------------------+

我希望将此时间舍入到最接近的值,时间步长为15分钟,以获得:

+------------------+
|TIME_15_MIN_STEP  |
+------------------+
|               930|
|              2200|
|              2200|
|              2200|
+------------------+

有谁知道怎么做?

非常感谢!!

2 个答案:

答案 0 :(得分:3)

一种更好的15分钟分组方法是在时间戳上使用pyspark.sql.functions.window

df = df \
   .groupBy(F.window("timestamp", "15 minutes")) \
   .withColumn("timestamp", F.col("window.start"))

请参阅文档here

答案 1 :(得分:1)

在不使用dt[,transaction := balance - shift(balance,1), by = id] 的情况下执行此操作的一种方法是首先将整数列转换为虚拟时间戳,然后执行与my answer中概述的similar question完全相同的操作}。最后将结果转换回所需格式的整数。

更全面的示例数据

我创建了一个具有更多可变性的示例来证明此方法正常工作。

udf

将整数列转换为虚拟时间戳

要将整数小时分钟列转换为时间戳,我们首先使用pyspark.sql.functions.format_string()add leading zeros到适当的时间。接下来,我们将一个虚拟日期(我使用data = sqlCtx.createDataFrame([(925,), (2205,), (2210,), (2242,), (2255,)], ["TIME"]) data.show() #+----+ #|TIME| #+----+ #| 925| #|2205| #|2210| #|2242| #|2255| #+----+ )与转换后的时间连接起来,并在结尾添加"2018-01-01"(几秒钟)。

":00"

计算抵消时间戳的分钟数

使用pyspark.sql.functions.minute()从虚拟时间戳中获取分钟。我们除以15,舍入,然后乘以15得到“新”分钟。 (这个逻辑在linked answer中有更详细的解释。)

data = data.withColumn("time_string", f.format_string("%04d", f.col("TIME")))\
    .withColumn(
        "time_string",
        f.concat_ws(
            ":",
            f.array(
                [
                    f.substring(
                        "time_string",
                        1,
                        2
                    ),
                    f.substring(
                        "time_string",
                        3,
                        2
                    ),
                    f.lit("00")
                ]
            )
        )
    )\
    .withColumn("time_string", f.concat(f.lit("2018-01-01 "), f.col("time_string")))

data.show()
#+----+-------------------+
#|TIME|        time_string|
#+----+-------------------+
#| 925|2018-01-01 09:25:00|
#|2205|2018-01-01 22:05:00|
#|2210|2018-01-01 22:10:00|
#|2242|2018-01-01 22:42:00|
#|2255|2018-01-01 22:55:00|
#+----+-------------------+

以秒为单位添加偏移量,转换回整数

data = data.withColumn("minute", f.minute("time_string"))\ .withColumn("new_minute", f.round(f.col("minute")/15)*15)\ .withColumn("minute_add", f.col("new_minute") - f.col("minute"))\ data.show() #+----+-------------------+------+----------+----------+ #|TIME| time_string|minute|new_minute|minute_add| #+----+-------------------+------+----------+----------+ #| 925|2018-01-01 09:25:00| 25| 30.0| 5.0| #|2205|2018-01-01 22:05:00| 5| 0.0| -5.0| #|2210|2018-01-01 22:10:00| 10| 15.0| 5.0| #|2242|2018-01-01 22:42:00| 42| 45.0| 3.0| #|2255|2018-01-01 22:55:00| 55| 60.0| 5.0| #+----+-------------------+------+----------+----------+ 列乘以60以获得以秒为单位的偏移量。将其添加到minute_add以获得“新”时间。

time_string