PySpark Window.partitionBy()将相同的单元格值视为不同

时间:2017-10-07 18:11:40

标签: pyspark apache-spark-sql window-functions

我有一个包含以下列的数据框:

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)

我想查找给定pidaction的第一个和最后一个时间戳。所以我这样做:

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()应该做什么吗?

0 个答案:

没有答案