我有如下DF:
Name starttime endtime
user1 2019-08-02 03:34:45 2019-08-02 03:52:03
user2 2019-08-13 13:34:10 2019-08-13 14:02:10
我想检查endtime
是否在接下来的一个小时内流血,是否确实将其更新为当前小时的最后一分钟和第二秒,如下所示。
Name starttime endtime
user1 2019-08-02 03:34:45 2019-08-02 03:52:03
user2 2019-08-13 13:34:10 2019-08-13 13:59:59
我可以使用UDF进行如下检查和替换,但不希望使用它们。
def adjust_end_hour(date):
return date.replace(second=59,minute=59)
adjust_end_hour_udf = udf(adjust_end_hour, TimestampType())
df = df.\
filter(df.endtime > adjust_end_hour_udf(df.starttime)).\
withColumn('enddtime', adjust_end_hour_udf(df.starttime))
如何在不使用pyspark中使用UDF的情况下做到这一点?
谢谢
假设您的DataFrame具有以下架构:
df.printSchema()
#root
# |-- Name: string (nullable = true)
# |-- starttime: timestamp (nullable = true)
# |-- endtime: timestamp (nullable = true)
即其中starttime
和endtime
均为TimestampType()
。
您可以通过比较TimestampType()
和endtime
的hour
部分来检查hour
是否渗出到下一小时。如果它们不等于1,则意味着您需要截断结束时间。
starttime
这会告诉您哪些行需要修改。在endtime
参数设置为from pyspark.sql.functions import col, hour
df.withColumn(
"bleeds_into_next_hour",
hour(col("endtime")) != hour(col("starttime"))
).show()
#+-----+-------------------+-------------------+---------------------+
#| Name| starttime| endtime|bleeds_into_next_hour|
#+-----+-------------------+-------------------+---------------------+
#|user1|2019-08-02 03:34:45|2019-08-02 03:52:03| false|
#|user2|2019-08-13 13:34:10|2019-08-13 14:02:10| true|
#+-----+-------------------+-------------------+---------------------+
的情况下,使用date_trunc
几乎可以达到所需的输出:
date_trunc
您现在所要做的就是从format
中减去1秒。最简单的方法是将hour
转换为1,然后再使用from pyspark.sql.functions import date_trunc, when
df.withColumn(
"bleeds_into_next_hour",
hour(col("endtime")) != hour(col("starttime"))
).withColumn(
"endtime",
when(
col("bleeds_into_next_hour"),
date_trunc('hour', "endtime")
).otherwise(col("endtime"))
).show()
#+-----+-------------------+-------------------+---------------------+
#| Name| starttime| endtime|bleeds_into_next_hour|
#+-----+-------------------+-------------------+---------------------+
#|user1|2019-08-02 03:34:45|2019-08-02 03:52:03| false|
#|user2|2019-08-13 13:34:10|2019-08-13 14:00:00| true|
#+-----+-------------------+-------------------+---------------------+
转换回。
endtime
将它们放在一起,没有中间列:
unix_timestamp
Notes
unix_timestamp
始终大于或等于from_unixtime
。您无法执行from_unixtime
,因为小时数会在12点后结束。