Python 如何在pyspark dataframe中检索每个窗口中的唯一值

Python 如何在pyspark dataframe中检索每个窗口中的唯一值,python,group-by,pyspark,apache-spark-sql,window,Python,Group By,Pyspark,Apache Spark Sql,Window,我有以下spark数据框: from pyspark.sql import SparkSession spark = SparkSession.builder.appName('').getOrCreate() df = spark.createDataFrame([(1, "a", "2"), (2, "b", "2"),(3, "c", "2"), (4, "d", "2"), (5, "b", "3"), (6, "b", "3"),(7, "c", "2"

我有以下spark数据框:

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('').getOrCreate()
df = spark.createDataFrame([(1, "a", "2"), (2, "b", "2"),(3, "c", "2"), (4, "d", "2"),
                (5, "b", "3"), (6, "b", "3"),(7, "c", "2")], ["nr", "column2", "quant"])
这让我回想起:

+---+-------+------+
| nr|column2|quant |
+---+-------+------+
|  1|      a|     2|
|  2|      b|     2|
|  3|      c|     2|
|  4|      d|     2|
|  5|      b|     3|
|  6|      b|     3|
|  7|      c|     2|
+---+-------+------+
我想检索每3个分组行(来自窗口大小为3的每个窗口)的行,其中quant列具有唯一值。如下图所示:

这里红色是窗口大小,每个窗口我只保留绿色行,其中quant是唯一的:

我希望得到的输出如下所示:

+---+-------+------+
| nr|column2|values|
+---+-------+------+
|  1|      a|     2|
|  4|      d|     2|
|  5|      b|     3|
|  7|      c|     2|
+---+-------+------+

我是spark的新手,因此,如果有任何帮助,我将不胜感激。谢谢

假设第3组记录基于“nr”列,这种方法应该适合您

使用决定是否应选择记录的
udf
,以及
lag
,可以获取上一行数据

def tag_selected(index, current_quant, prev_quant1, prev_quant2):                                                                                                    
    if index % 3 == 1:  # first record in each group is always selected                                                                                              
        return True                                                                                                                                                  
    if index % 3 == 2 and current_quant != prev_quant1: # second record will be selected if prev quant is not same as current                                        
        return True                                                                                                                                                  
    if index % 3 == 0 and current_quant != prev_quant1 and current_quant != prev_quant2: # third record will be selected if prev quant are not same as current       
        return True                                                                                                                                                  
    return False                                                                                                                                                     

tag_selected_udf = udf(tag_selected, BooleanType())                                                                                                                  

结果是什么

+---+-------+-----+
| nr|column2|quant|
+---+-------+-----+
|  1|      a|    2|
|  4|      d|    2|
|  5|      b|    3|
|  7|      c|    2|
+---+-------+-----+

假设分组3记录是基于“nr”列的,这种方法应该适合您

使用决定是否应选择记录的
udf
,以及
lag
,可以获取上一行数据

def tag_selected(index, current_quant, prev_quant1, prev_quant2):                                                                                                    
    if index % 3 == 1:  # first record in each group is always selected                                                                                              
        return True                                                                                                                                                  
    if index % 3 == 2 and current_quant != prev_quant1: # second record will be selected if prev quant is not same as current                                        
        return True                                                                                                                                                  
    if index % 3 == 0 and current_quant != prev_quant1 and current_quant != prev_quant2: # third record will be selected if prev quant are not same as current       
        return True                                                                                                                                                  
    return False                                                                                                                                                     

tag_selected_udf = udf(tag_selected, BooleanType())                                                                                                                  

结果是什么

+---+-------+-----+
| nr|column2|quant|
+---+-------+-----+
|  1|      a|    2|
|  4|      d|    2|
|  5|      b|    3|
|  7|      c|    2|
+---+-------+-----+


你如何创建你的红色团队?您的分组条件是什么?前3行是一个组,后3行是下一个组。从顶部按什么排序。数据集已排序。前三行是一个组,下三行是下一个组。它应该在分布式文件系统或数据库中没有排序。它就像一袋弹珠,你可以把它们从袋子里拣出来,但不能从里面拣出来。你如何创建你的红色群组?您的分组条件是什么?前3行是一个组,后3行是下一个组。从顶部按什么排序。数据集已排序。前三行是一个组,下三行是下一个组。它应该在分布式文件系统或数据库中没有排序。它就像一袋弹珠,你可以把它们从袋子里拣出来,但不能放在里面。@Sascha,如果它对你有用,你能接受这个答案吗,谢谢。首先谢谢你的帮助,我对这个代码有疑问,所以在
df.withColumn(“prev_quant1”,lag(col(“quant”),1,None)。在(窗口))..
每次我们创建新列时?这意味着在这种情况下,如果数据较大,会占用太多内存?第二个问题是关于
def tag_selected
。这是否意味着它的工作原理类似于滚动窗口,但不将3行(1,2,3)和下3行(4,5,6)作为一个不同的组?因为当我运行这个时,我得到了一个1,4,5,6,7的输出。是否可以将窗口大小定义为3?rdd/df/数据集上的转换将创建新的rdd作为rdd不可变。因此,添加新列会创建新的rdd实例,但spark memory management会决定旧rdd是否需要保留或清除。选择tag_会像滚动窗口一样获取当前的、先前的数量,但内部的逻辑会忽略其他窗口元素。对于ex 4th row,使用第2行、第3行数据调用udf,但udf会忽略,因为它根据索引知道它是组的第一行,并且始终需要选择。如果索引%3==0,则代码不应在udf中选择6作为条件。。。。。。失败并返回False。谢谢您的解释。我想再澄清一件事。如果spark数据帧已按nr排序,但nr不是从1开始,该怎么办。例如,nr的顺序如下:“15.3、22.8、37.1、39、56等”。在这种情况下,最好添加新的索引列并遵循该逻辑?或者关于nr还有其他选择吗?是的,如果nr值不是索引号,那么您需要添加新的列作为索引号。@Sascha,如果它对您有效,请接受这个作为答案,谢谢。首先感谢您的帮助,我对这个代码有疑问,所以在
df.withColumn(“prev_quant1”),lag(col(“quant”),1,无)。在(窗口)上方…
每次我们创建新列时?这意味着在这种情况下,如果数据较大,会占用太多内存?第二个问题是关于
def tag_selected
。这是否意味着它的工作原理类似于滚动窗口,但不将3行(1,2,3)和下3行(4,5,6)作为一个不同的组?因为当我运行这个时,我得到了一个1,4,5,6,7的输出。是否可以将窗口大小定义为3?rdd/df/数据集上的转换将创建新的rdd作为rdd不可变。因此,添加新列会创建新的rdd实例,但spark memory management会决定旧rdd是否需要保留或清除。选择tag_会像滚动窗口一样获取当前的、先前的数量,但内部的逻辑会忽略其他窗口元素。对于ex 4th row,使用第2行、第3行数据调用udf,但udf会忽略,因为它根据索引知道它是组的第一行,并且始终需要选择。如果索引%3==0,则代码不应在udf中选择6作为条件。。。。。。失败并返回False。谢谢您的解释。我想再澄清一件事。如果spark数据帧已按nr排序,但nr不是从1开始,该怎么办。例如,nr的顺序如下:“15.3、22.8、37.1、39、56等”。在这种情况下,最好添加新的索引列并遵循该逻辑?或者是否有其他关于nr的选项?是的,如果nr值不是索引编号,则需要添加新的列作为索引编号。