Python PySpark:使用窗口函数滚动数据帧
我有一个包含4列的数据框my_df:Python PySpark:使用窗口函数滚动数据帧,python,python-3.x,dataframe,pyspark,window-functions,Python,Python 3.x,Dataframe,Pyspark,Window Functions,我有一个包含4列的数据框my_df: +----------------+---------------+--------+---------+ | user_id| domain|isp_flag|frequency| +----------------+---------------+--------+---------+ | josh| wanadoo.fr| 1| 15| | jo
+----------------+---------------+--------+---------+
| user_id| domain|isp_flag|frequency|
+----------------+---------------+--------+---------+
| josh| wanadoo.fr| 1| 15|
| josh| random.it| 0| 12|
| samantha| wanadoo.fr| 1| 16|
| bob| eidsiva.net| 1| 5|
| bob| media.net| 0| 1|
| dylan| vodafone.it| 1| 448|
| dylan| somesite.net| 0| 20|
| dylan| yolosite.net| 0| 49|
| dylan| random.it| 0| 3|
| don| vodafone.it| 1| 39|
| don| popsugar.com| 0| 10|
| don| fabio.com| 1| 49|
+----------------+---------------+--------+---------+
这就是我计划做的-
查找isp_标志为0的最大频域的频率小于isp_标志为1的最大频域的25%的所有用户_id
在上面的例子中,我的输出-
+----------------+---------------+--------+---------+
| user_id| domain|isp_flag|frequency|
+----------------+---------------+--------+---------+
| bob| eidsiva.net| 1| 5|
| bob| media.net| 0| 1|
| dylan| vodafone.it| 1| 448|
| dylan| yolosite.net| 0| 49|
| don| fabio.com| 1| 49|
| don| popsugar.com| 0| 10|
+----------------+---------------+--------+---------+
我相信我需要窗口函数来实现这一点,因此我尝试了以下步骤,首先分别为每个用户标识找到isp_flag=0和isp_flag=1的最大频域-
我做错了什么?如何获得上面打印的最终输出?IIUC,您可以尝试以下操作:分别为isp_标志=0或1的每个用户计算最大频率max_0,max_1。然后根据条件max_0<0.25*max_1和max_1中的频率加上max_0进行过滤,以仅选择具有最大频率的记录
from pyspark.sql import Window, functions as F
# set up the Window to calculate max_0 and max_1 for each user
# having isp_flag = 0 and 1 respectively
w1 = Window.partitionBy('user_id').rowsBetween(Window.unboundedPreceding, Window.unboundedFollowing)
df.withColumn('max_1', F.max(F.expr("IF(isp_flag==1, frequency, NULL)")).over(w1))\
.withColumn('max_0', F.max(F.expr("IF(isp_flag==0, frequency, NULL)")).over(w1))\
.where('max_0 < 0.25*max_1 AND frequency in (max_1, max_0)') \
.show()
+-------+------------+--------+---------+-----+-----+
|user_id| domain|isp_flag|frequency|max_1|max_0|
+-------+------------+--------+---------+-----+-----+
| don|popsugar.com| 0| 10| 49| 10|
| don| fabio.com| 1| 49| 49| 10|
| dylan| vodafone.it| 1| 448| 448| 49|
| dylan|yolosite.net| 0| 49| 448| 49|
| bob| eidsiva.net| 1| 5| 5| 1|
| bob| media.net| 0| 1| 5| 1|
+-------+------------+--------+---------+-----+-----+
每个请求的一些解释:
WindowSpec w1设置为检查同一用户PartitionBy的所有记录,以便F.max函数将基于同一用户比较所有行
我们使用IFisp_flag==1,frequency,NULL来查找isp_flag==1的行的频率,当isp_flag不是1时,它返回NULL,因此在F.max函数中被跳过。这是一个SQL表达式,因此我们需要F.expr函数来运行它
F.max…overv1将获取执行上述SQL表达式的结果的最大值。此计算基于窗口w1
这很有效,谢谢!你能解释一下窗户的功能吗?另外,F.maxF.exprIFisp_flag==1,frequency,NULL在这里做什么?为什么里面有空值?@kev在帖子中添加了一些解释。谢谢你的解释!还有,为什么我们在WHERE子句中需要max_1和max_0中的频率?嗨,@kev,我看到你的过滤器中有rank==1,而max_1中的频率,max_0基本上是通过频率的最大值进行过滤,这与rank==1是一样的。只是提醒一下,如果与max_1或max_0.BTW有联系,每个用户将获得超过2行。您可以从w1中删除.rowsBetweenWindow.UnbounddReceiding、Window.unboundedFollowing,因为当WindowSpec中没有orderBy子句时,它是默认的无界。
from pyspark.sql import Window, functions as F
# set up the Window to calculate max_0 and max_1 for each user
# having isp_flag = 0 and 1 respectively
w1 = Window.partitionBy('user_id').rowsBetween(Window.unboundedPreceding, Window.unboundedFollowing)
df.withColumn('max_1', F.max(F.expr("IF(isp_flag==1, frequency, NULL)")).over(w1))\
.withColumn('max_0', F.max(F.expr("IF(isp_flag==0, frequency, NULL)")).over(w1))\
.where('max_0 < 0.25*max_1 AND frequency in (max_1, max_0)') \
.show()
+-------+------------+--------+---------+-----+-----+
|user_id| domain|isp_flag|frequency|max_1|max_0|
+-------+------------+--------+---------+-----+-----+
| don|popsugar.com| 0| 10| 49| 10|
| don| fabio.com| 1| 49| 49| 10|
| dylan| vodafone.it| 1| 448| 448| 49|
| dylan|yolosite.net| 0| 49| 448| 49|
| bob| eidsiva.net| 1| 5| 5| 1|
| bob| media.net| 0| 1| 5| 1|
+-------+------------+--------+---------+-----+-----+