Apache spark Pyspark—整数表示的四舍五入时间,精确到四分之一小时(15分钟)

Apache spark Pyspark—整数表示的四舍五入时间,精确到四分之一小时(15分钟),apache-spark,pyspark,apache-spark-sql,rounding,Apache Spark,Pyspark,Apache Spark Sql,Rounding,我正在Pyspark上开发一个数据帧。一列由时间对应的整数值组成: 数据。选择“时间”。显示4 +---------+ |时间| +---------+ | 925| | 2205| | 2205| | 2205| +---------+ 我希望以15分钟的时间步长将此时间四舍五入到最接近的值,以便获得: +---------+ |时间15分钟步长| +---------+ |

我正在Pyspark上开发一个数据帧。一列由时间对应的整数值组成:

数据。选择“时间”。显示4 +---------+ |时间| +---------+ | 925| | 2205| | 2205| | 2205| +---------+ 我希望以15分钟的时间步长将此时间四舍五入到最接近的值,以便获得:

+---------+ |时间15分钟步长| +---------+ | 930| | 2200| | 2200| | 2200| +---------+ 有人知道怎么做吗


非常感谢

不使用udf的一种方法是首先将整型列转换为伪时间戳,然后执行与中所述的基本相同的操作。最后将结果转换回所需格式的整数

更全面的示例数据

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

data=sqlCtx.createDataFrame[925、2205、2210、2242、2255、],[TIME] 数据显示 +--+ |时间| +--+ | 925| |2205| |2210| |2242| |2255| +--+ 将整型列转换为伪时间戳

要将整数hour-minute列转换为时间戳,我们首先在适当的时候使用To。接下来,我们将我使用的一个虚拟日期2018-01-01与转换后的时间连接起来,并在末尾添加:00,以秒为单位

数据=data.withColumntime\u字符串,f.format\u字符串%04d,f.colTIME\ .withColumn 时间线, f、 海螺 :, f、 排列 [ f、 子串 时间线, 1. 2. , f、 子串 时间线, 3. 2. , f、 利特00 ] \ .带ColumnTime_字符串,f.concatf.lit2018-01-01,f.ColumnTime_字符串 数据显示 +--+----------+ |时间|时间_字符串| +--+----------+ | 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| +--+----------+ 计算偏移时间戳的分钟数

用于从虚拟时间戳获取分钟。我们除以15,四舍五入,然后乘以15得到新的分钟数。此逻辑将在中进行更详细的解释

数据=data.withColumnminute,f.minutetime\u字符串\ .带新列每分钟,f.roundf.colminute/15*15\ .使用列分钟添加,f.colnew\u分钟-f.colminute\ 数据显示 +--+----------+---+-----+-----+ |时间|时间|字符串|分钟|新|分钟|分钟|添加| +--+----------+---+-----+-----+ | 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| +--+----------+---+-----+-----+ 以秒为单位添加偏移量,转换回整数

将minute_add列乘以60,得到以秒为单位的偏移量。将其添加到时间字符串以获取新时间

data=data.withColumn 新时代, f、 从\u unixtimef.unix\u timestamptime\u string+f.colminute\u add*60 \ .withColumn 新时代, f、 格式字符串%02d%02d,f.hournew\u时间,f.minutenew\u时间.castint data.selectTIME,NEW\u TIME.show +--+----+ |时间|新时间| +--+----+ | 925| 930| |2205| 2200| |2210| 2215| |2242| 2245| |2255| 2300| +--+----+
在不使用udf的情况下实现这一点的一种方法是首先将整数列转换为伪时间戳,然后执行与中概述的基本相同的操作。最后将结果转换回所需格式的整数

更全面的示例数据

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

data=sqlCtx.createDataFrame[925、2205、2210、2242、2255、],[TIME] 数据显示 +--+ |时间| +--+ | 925| |2205| |2210| |2242| |2255| +--+ 将整型列转换为伪时间戳

要将整数hour-minute列转换为时间戳,我们首先在适当的时候使用To。接下来,我们将我使用的一个虚拟日期2018-01-01与转换后的时间连接起来,并在末尾添加:00,以秒为单位

数据=data.withColumntime\u字符串,f.format\u字符串%04d,f.colTIME\ .withColumn 时间线, f、 海螺 :, f、 排列 [ f、 子串 时间线, 1. 2. , f、 子串 时间线, 3. 2. , f、 利特00 ] \ .带ColumnTime_字符串,f.concatf.lit2018-01-01,f.ColumnTime_字符串 数据显示 +--+----------+ |时间|时间_字符串| +--+----------+ | 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| +--+----------+ 计算偏移时间戳的分钟数

用于从虚拟时间戳获取分钟。我们除以15,四舍五入,然后乘以15得到新的分钟数。此逻辑将在中进行更详细的解释

数据=data.withColumnminute,f.minutetime\u字符串\ .带新列每分钟,f.roundf.colminute/15*15\ .使用列分钟添加,f.colnew\u分钟-f.colminute\ 数据显示 +--+----------+---+-----+-----+ |时间|时间|字符串|分钟|新|分钟|分钟|添加| +--+----------+---+-----+-----+ | 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| +--+----------+---+-----+-----+ 以秒为单位添加偏移量,转换回整数

将minute_add列乘以60,得到以秒为单位的偏移量。将其添加到时间字符串以获取新时间

data=data.withColumn 新时代, f、 从\u unixtimef.unix\u timestamptime\u string+f.colminute\u add*60 \ .withColumn 新时代, f、 格式字符串%02d%02d,f.hournew\u时间,f.minutenew\u时间.castint data.selectTIME,NEW\u TIME.show +--+----+ |时间|新时间| +--+----+ | 925| 930| |2205| 2200| |2210| 2215| |2242| 2245| |2255| 2300| +--+----+
按15分钟分组的更好方法是在时间戳上使用pyspark.sql.functions.window:

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

请参阅文档

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

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

参见文档

我想对于925,算法应该检查925是否更接近930或915,这是最接近的15倍值。我不明白为什么2205变成了2200?2205已经是15的倍数,这是舍入背后的逻辑?因为它们表示时间2205=22:05=10:05 pm。是否有一些特定的原因将时间表示为整数925而不是字符串09:25?如果时间是时间戳(例如,从历元算起的毫秒),则可以方便地将时间表示为整数;如果时间是小时或日期,则可以将时间表示为字符串,并且在这两种情况下都可以执行许多操作使用UDF。第一步将此时间转换为正常日期时间,然后使用它。我想对于925,算法应该检查925是否更接近930或915,这是最接近的15倍值。我不明白为什么2205变成了2200?2205已经是15的倍数,这是舍入背后的逻辑?因为它们表示时间2205=22:05=10:05 pm。是否有一些特定的原因将时间表示为整数925而不是字符串09:25?如果时间是时间戳(例如,从历元算起的毫秒),则可以方便地将时间表示为整数;如果时间是小时或日期,则可以将时间表示为字符串,并且在这两种情况下都可以执行许多操作使用UDF。第一步将这个时间转换为正常的日期时间,然后使用它,你就是一个学者和绅士。这是一个很好的答案,虽然下面的答案看起来也不错。你是一位学者和绅士。这是一个非常好的答案,尽管下面的答案看起来也不错。