Pyspark中带有when条件的Groupby
我的数据框看起来像Pyspark中带有when条件的Groupby,pyspark,pyspark-sql,pyspark-dataframes,Pyspark,Pyspark Sql,Pyspark Dataframes,我的数据框看起来像 id |reg_date | txn_date| +----------+----------+--------------------+ |1 |2019-01-06| 2019-02-15 12:51:15| |1 |2019-01-06| 2019-03-29 13:15:27| |1 |2019-01-06| 2019-06-01 01:42:57| |1 |2019
id |reg_date | txn_date|
+----------+----------+--------------------+
|1 |2019-01-06| 2019-02-15 12:51:15|
|1 |2019-01-06| 2019-03-29 13:15:27|
|1 |2019-01-06| 2019-06-01 01:42:57|
|1 |2019-01-06| 2019-01-06 17:01:...|
|5 |2019-06-16| 2019-07-19 11:50:34|
|5 |2019-06-16| 2019-07-13 19:49:39|
|5 |2019-06-16| 2019-08-27 17:37:22|
|2 |2018-07-30| 2019-01-01 07:03:...|
|2 |2018-07-30| 2019-07-30 01:27:57|
|2 |2018-07-30| 2019-02-01 00:08:35
我想拾取reg\u日期
之后的第一个txn\u日期
,即reg\u日期>=txn\u日期
的第一个txn\u日期
预期产量
id |reg_date | txn_date|
+----------+----------+--------------------+
|1 |2019-01-06| 2019-01-06 17:01:...|
|5 |2019-06-16| 2019-07-13 19:49:39|
|2 |2018-07-30| 2019-07-30 01:27:57|
到目前为止,我已经做到了
df = df.withColumn('txn_date',to_date(unix_timestamp(F.col('txn_date'),'yyyy-MM-dd HH:mm:ss').cast("timestamp")))
df = df.withColumn('reg_date',to_date(unix_timestamp(F.col('reg_date'),'yyyy-MM-dd').cast("timestamp")))
gg = df.groupBy('id','reg_date').agg(min(F.col('txn_date')))
但是得到了错误的结果。条件
reg\u date>=txn\u date
可能不明确
2019-01-06>=2019-01-06 17:01:30
是指2019-01-06 00:00:00>=2019-01-06 17:01:30
还是2019-01-06 23:59:59>=2019-01-06 17:01:30
在您的示例中,2019-01-06>=2019-01-06 17:01:30
被评估为真,因此我假设是后一种情况,即23:59:59的情况
从上面的假设出发,下面是我如何编码它的
import pyspark.sql.functions as F
#create a sample data frame
data = [('2019-01-06','2019-02-15 12:51:15'),('2019-01-06','2019-03-29 13:15:27'),('2019-01-06','2019-01-06 17:01:30'),\
('2019-07-30','2019-07-30 07:03:01'),('2019-07-30','2019-07-30 01:27:57'),('2019-07-30','2019-07-30 00:08:35')]
cols = ('reg_date', 'txn_date')
df = spark.DataFrame(data,cols)
#add 23:59:59 to reg_date as a dummy_date for a timestamp comparison later
df = df.withColumn('dummy_date', F.concat(F.col('reg_date'), F.lit(' 23:59:59')))
#convert columns to the appropriate time data types
df = df.select([F.to_date(F.col('reg_date'),'yyyy-MM-dd').alias('reg_date'),\
F.to_timestamp(F.col('txn_date'),'yyyy-MM-dd HH:mm:ss').alias('txn_date'),\
F.to_timestamp(F.col('dummy_date'),'yyyy-MM-dd HH:mm:ss').alias('dummy_date')])
#implementation part
(df.orderBy('reg_date')
.filter(F.col('dummy_date')>=F.col('txn_date'))
.groupBy('reg_date')
.agg(F.first('txn_date').alias('txn_date'))
.show())
#+----------+----------------------+
#| reg_date| txn_date|
#+----------+----------------------+
#|2019-01-06| 2019-01-06 17:01:30|
#|2019-07-30| 2019-07-30 07:03:01|
#+----------+----------------------+
你不需要点菜。您可以使用过滤器丢弃所有较小的值,然后按id聚合并获得较小的时间戳,因为第一个时间戳将是最小值。比如:
df.filter(df.reg_date >= df.txn_date) \
.groupBy(df.reg_date) \
.agg(F.min(df.txn_date)) \
.show()
如果您已经准备好创建dataframe的数据,那就太好了。您得到的输出是什么@清管器-有两个条件。一个是reg_date>=txn_date,另一个基于此过滤器,使用groupby操作查找reg_date之后的min.txn_date。在我的例子中,我得到了一些满足reg_date