Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python PySpark:使用窗口函数滚动数据帧_Python_Python 3.x_Dataframe_Pyspark_Window Functions - Fatal编程技术网

Python PySpark:使用窗口函数滚动数据帧

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

我有一个包含4列的数据框my_df:

+----------------+---------------+--------+---------+
|         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|
+-------+------------+--------+---------+-----+-----+