我有一个包含以下列的数据框:
df_lp.show()
+--------------------+-------------+--------------------+------+
| ts| uid| pid|action|
+--------------------+-------------+--------------------+------+
|2017-03-28 09:34:...|1950269663250|IST334-0149064968...| <L|
|2017-03-31 05:50:...|S578448696405|IST334-0149089179...| <L|
|2017-03-28 09:38:...|1950269663250|IST334-0149064968...| <L|
|2017-03-30 09:26:...| 412310802992|IST334-1212011845...| <L|
ts
是时间戳,所有其他列都是字符串。 action
可以从一组值中选择一个(<L
,+L
,<B
,+B
等。
现在我定义了一个窗口,以及两个窗口函数:
ts_w_lp = Window.partitionBy(df_lp['pid']).orderBy(df_lp['ts'].asc())
first_lp = fns.min(df_lp['ts']).over(ts_w_lp)
last_lp = fns.max(df_lp['ts']).over(ts_w_lp)
我想查找给定pid
和action
的第一个和最后一个时间戳。所以我这样做:
df_lp_pB = df_lp.filter(df_lp['action'] == '+B')\
.select('pid', first_lp.alias('tsf'), last_lp.alias('tsl'))\
.distinct().sort('pid')
然而,我得到的数据帧有额外的行,其中一个窗口函数似乎有中间值。
df_lp_pB.filter('pid = "BAG26723881"').toPandas()
pid tsf tsl
0 BAG26723881 2017-04-11 15:10:35.674 2017-04-11 15:10:35.674
1 BAG26723881 2017-04-11 15:10:35.674 2017-04-11 15:10:35.736
如果我对Spark SQL执行相同的操作,它会按预期工作。
df_lp.createOrReplaceTempView('scans_lp')
df_sql = spark.sql("SELECT pid , min(ts) AS tsf, max(ts) AS tsl FROM scans_lp \
WHERE action='+B' GROUP BY pid ORDER BY pid")
df_sql.filter('pid = "BAG26723881"').toPandas()
pid tsf tsl
0 BAG26723881 2017-04-11 15:10:35.674 2017-04-11 15:10:35.736
实际上,当我将timestamp列的排序反转为降序时,另一个窗口函数会出现问题!
ts_w_lp2 = Window.partitionBy(df_lp['pid']).orderBy(df_lp['ts'].desc())
first_lp2 = fns.min(df_lp['ts']).over(ts_w_lp2)
last_lp2 = fns.max(df_lp['ts']).over(ts_w_lp2)
df_lp_pB2 = df_lp.filter(df_lp['action'] == '+B')\
.select('pid', first_lp2.alias('tsf'), last_lp2.alias('tsl'))\
.distinct().sort('pid')
df_lp_pB2.filter('pid = "BAG26723881"').toPandas()
pid tsf tsl
0 BAG26723881 2017-04-11 15:10:35.736 2017-04-11 15:10:35.736
1 BAG26723881 2017-04-11 15:10:35.674 2017-04-11 15:10:35.736
如果我进一步调查,我会看到我的所有pid
被认为是不同的,即使对于他们不是的行也是如此!见:
df_lp.filter('action = "+B"').select('pid').distinct().count()
6382
df_sql.count()
6382
df_lp.filter('action = "+B"').select('pid').count()
120303
df_lp_pB.count()
120303
发生了什么事?我误解了Window.partitionBy()
应该做什么吗?