2017-09-22 56 views
1

我想基於當前輸入行限制聚合函數使用窗口框架中的哪些行。例如,給定一個數據幀df和窗口w,我希望能夠做一些事情,如:[Py] Spark SQL:使用框架的輸入行限制窗口的每個框架

df2 = df.withColumn("foo", first(col("bar").filter(...)).over(w)) 

其中.filter將基於幀的輸入行的當前窗口幀刪除行。

我的具體使用情況如下:給定一個數據幀df

+-----+--+--+ 
|group|n1|n2| 
+-----+--+--+ 
| 1| 1| 6| 
| 1| 0| 3| 
| 1| 2| 2| 
| 1| 3| 5| 
| 2| 0| 5| 
| 2| 0| 7| 
| 2| 3| 2| 
| 2| 5| 9| 
+-----+--+--+ 

窗口

w = Window.partitionBy("group")\ 
      .orderBy("n1", "n2")\ 
      .rowsBetween(Window.currentRow + 1, Window.unboundedFollowing) 

和一些積極的龍i,你會如何找到在每個輸入的第一行(fr)行r的幀,使得r.n1 < fr.n1, r.n2 < fr.n2和max(fr.n1 - r.n1,fr.n2 - r.n2)< i?返回的值可以是fr.n1fr的行索引df。因此,對於i = 6,輸出爲例如df

+-----+--+--+-----+ 
|group|n1|n2|fr.n1| 
+-----+--+--+-----+ 
| 1| 1| 6| null| 
| 1| 0| 3| 1| 
| 1| 2| 2| 3| 
| 1| 3| 5| null| 
| 2| 0| 5| 5| 
| 2| 0| 7| 5| 
| 2| 3| 2| null| 
| 2| 5| 9| null| 
+-----+--+--+-----+ 

我一直在學習星火API和望着Windowfirstwhen例子,但我似乎無法計件它在一起。這是甚至可能與窗口和聚合函數,或者我完全不符合標準?

+1

你可以請一些例子來解釋一下,你真正想要做的問題現在給出的問題並不清楚。如果'|,則爲 –

+0

2 | 3 | 2 | 5 |'是真的那麼怎麼來'| 1 | 2 | 2 | 3 |'是真的嗎?反之亦然。他們互相矛盾。請檢查您的最終df。 –

+0

糟糕!我更新了原來的示例解決方案以便正確。我還在一開始就給出了一個總體描述的例子,希望能夠讓事情更加清晰。 – alan

回答

1

你將不能夠只用窗函數和聚合做到這一點,你需要一個自聯接: 對於加盟:

df = sc.parallelize([[1, 1, 6],[1, 0, 3],[1, 2, 2],[1, 3, 5],[2, 0, 5],[2, 0, 7],[2, 3, 2],[2, 5, 9]]).toDF(["group","n1","n2"]) 

import pyspark.sql.functions as psf 
df_r = df.select([df[c].alias("r_" + c) for c in df.columns]) 
df_join = df_r\ 
    .join(df, (df_r.r_group == df.group) 
     & (df_r.r_n1 < df.n1) 
     & (df_r.r_n2 < df.n2) 
     & (psf.greatest(df.n1 - df_r.r_n1, df.n2 - df_r.r_n2) < i), "leftouter")\ 
    .drop("group") 

現在我們可以將窗函數只保持第一行:

w = Window.partitionBy("r_group", "r_n1", "r_n2").orderBy("n1", "n2") 
res = df_join\ 
    .withColumn("rn", psf.row_number().over(w))\ 
    .filter("rn = 1").drop("rn") 

    +-------+----+----+----+----+ 
    |r_group|r_n1|r_n2| n1| n2| 
    +-------+----+----+----+----+ 
    |  1| 0| 3| 1| 6| 
    |  1| 1| 6|null|null| 
    |  1| 2| 2| 3| 5| 
    |  1| 3| 5|null|null| 
    |  2| 0| 5| 5| 9| 
    |  2| 0| 7| 5| 9| 
    |  2| 3| 2|null|null| 
    |  2| 5| 9|null|null| 
    +-------+----+----+----+----+ 
+0

感謝您的回答。這是有道理的,它會需要一個連接,因爲這實際上是篩選窗口框架將要做的事情,至少在我的具體情況中。 – alan