Python PySpark 1.5如何将时间戳从秒截断为最接近的分钟

Python PySpark 1.5如何将时间戳从秒截断为最接近的分钟,python,datetime,apache-spark,apache-spark-sql,pyspark,Python,Datetime,Apache Spark,Apache Spark Sql,Pyspark,我正在使用PySpark。我在数据帧('canon_evt')中有一列('dt'),这是一个时间戳。我正在尝试从DateTime值中删除秒数。它最初是作为字符串从拼花地板读入的。然后我尝试通过将其转换为时间戳 canon_evt = canon_evt.withColumn('dt',to_date(canon_evt.dt)) canon_evt= canon_evt.withColumn('dt',canon_evt.dt.astype('Timestamp')) 然后我想删除秒。我尝试了

我正在使用PySpark。我在数据帧('canon_evt')中有一列('dt'),这是一个时间戳。我正在尝试从DateTime值中删除秒数。它最初是作为字符串从拼花地板读入的。然后我尝试通过将其转换为时间戳

canon_evt = canon_evt.withColumn('dt',to_date(canon_evt.dt))
canon_evt= canon_evt.withColumn('dt',canon_evt.dt.astype('Timestamp'))
然后我想删除秒。我尝试了“trunc”、“date\u格式”,甚至尝试像下面这样将片段连接在一起。我认为它需要某种映射和lambda组合,但我不确定时间戳是否是一种合适的格式,以及是否有可能去掉秒

canon_evt = canon_evt.withColumn('dyt',year('dt') + '-' + month('dt') +
    '-' + dayofmonth('dt') + ' ' + hour('dt') + ':' + minute('dt'))

[Row(dt=datetime.datetime(2015, 9, 16, 0, 0),dyt=None)]

火花>=2.3

您可以使用
date\u trunc

df.withColumn("dt_truncated", date_trunc("minute", col("dt"))).show()

## +-------------------+-------------------+
## |                 dt|       dt_truncated|
## +-------------------+-------------------+
## |1970-01-01 00:00:00|1970-01-01 00:00:00|
## |2015-09-16 05:39:46|2015-09-16 05:39:00|
## |2015-09-16 05:40:46|2015-09-16 05:40:00|
## |2016-03-05 02:00:10|2016-03-05 02:00:00|
## +-------------------+-------------------+
火花<2.3

转换为Unix时间戳和基本算法应符合以下技巧:

from pyspark.sql import Row
from pyspark.sql.functions import col, unix_timestamp, round

df = sc.parallelize([
    Row(dt='1970-01-01 00:00:00'),
    Row(dt='2015-09-16 05:39:46'),
    Row(dt='2015-09-16 05:40:46'),
    Row(dt='2016-03-05 02:00:10'),
]).toDF()


## unix_timestamp converts string to Unix timestamp (bigint / long)
## in seconds. Divide by 60, round, multiply by 60 and cast
## should work just fine.
## 
dt_truncated = ((round(unix_timestamp(col("dt")) / 60) * 60)
    .cast("timestamp"))

df.withColumn("dt_truncated", dt_truncated).show(10, False)
## +-------------------+---------------------+
## |dt                 |dt_truncated         |
## +-------------------+---------------------+
## |1970-01-01 00:00:00|1970-01-01 00:00:00.0|
## |2015-09-16 05:39:46|2015-09-16 05:40:00.0|
## |2015-09-16 05:40:46|2015-09-16 05:41:00.0|
## |2016-03-05 02:00:10|2016-03-05 02:00:00.0|
## +-------------------+---------------------+

我认为zero323有最好的答案。考虑到它的实现有多容易,Spark不支持它,这有点恼人。为了子孙后代,我使用了一个函数:

def trunc(date, format):
    """Wraps spark's trunc fuction to support day, minute, and hour"""
    import re
    import pyspark.sql.functions as func

    # Ghetto hack to get the column name from Column object or string:
    try:
        colname = re.match(r"Column<.?'(.*)'>", str(date)).groups()[0]
    except AttributeError:
        colname = date

    alias = "trunc(%s, %s)" % (colname, format)

    if format in ('year', 'YYYY', 'yy', 'month', 'mon', 'mm'):
        return func.trunc(date, format).alias(alias)
    elif format in ('day', 'DD'):
        return func.date_sub(date, 0).alias(alias)
    elif format in ('min', ):
        return ((func.round(func.unix_timestamp(date) / 60) * 60).cast("timestamp")).alias(alias)
    elif format in ('hour', ):
        return ((func.round(func.unix_timestamp(date) / 3600) * 3600).cast("timestamp")).alias(alias)
def trunc(日期、格式):
“”“包装spark的trunc功能以支持日、分钟和小时”“”
进口稀土
将pyspark.sql.functions作为func导入
#Ghetto hack可从列对象或字符串获取列名:
尝试:
colname=re.match(r“Column”,str(date)).groups()[0]
除属性错误外:
colname=日期
alias=“trunc(%s,%s)”%(colname,格式)
如果格式为('year'、'yyy'、'yy'、'month'、'mon'、'mm'):
返回函数trunc(日期、格式).alias(别名)
elif格式为('day','DD'):
返回函数日期(日期,0)别名(别名)
elif格式为('min',):
return((func.round(func.unix_时间戳(日期)/60)*60.cast(“时间戳”)).alias(别名)
elif格式(小时):
return((func.round(func.unix_时间戳(日期)/3600)*3600.cast(“时间戳”)).alias(别名)

这个问题是几年前提出的,但是如果其他人遇到它,从Spark v2.3开始,它已经作为一项功能添加。现在,这很简单(假设
canon_evt
是一个带有时间戳列
dt
的数据帧,我们希望从中删除秒)


将时间戳截断为其他分钟,例如5分钟或10分钟或7分钟

from pyspark.sql.functions import *
df = spark.createDataFrame([("2016-03-11 09:00:07", 1, 5),("2016-03-11 09:00:57", 2, 5)]).toDF("date", "val","val2")
w = df.groupBy('val',window("date", "5 seconds")).agg(sum("val1").alias("sum"))
w.select(w.window.start.cast("string").alias("start"),w.window.end.cast("string").alias("end"), "sum", "val").show(10, False)

你能贴出你读拼花地板时的样子吗?[Row(dt='2015-09-16 05:39:46')],Row(dt='2015-09-16 05:40:46')]'zero323',谢谢你的快速帮助!但是,如果我只能访问Spark 1.3,因此没有“unix_timestamp”函数,那么在Spark SQL或DataFrame中执行它还会很容易吗?谢谢!你的回答正是我想要找到的。请注意,小时trunc将在29分钟以上的时间内凑到下一个小时。12:15是12:00,12:30是13:00。如果您寻找截断函数,它可能不是所需的函数。
from pyspark.sql.functions import *
df = spark.createDataFrame([("2016-03-11 09:00:07", 1, 5),("2016-03-11 09:00:57", 2, 5)]).toDF("date", "val","val2")
w = df.groupBy('val',window("date", "5 seconds")).agg(sum("val1").alias("sum"))
w.select(w.window.start.cast("string").alias("start"),w.window.end.cast("string").alias("end"), "sum", "val").show(10, False)