簡體   English   中英

在Spark中以非恆定幀大小應用窗口功能

[英]Apply window function in Spark with non constant frame size

我的問題

我目前在使用Spark窗口功能時遇到困難。 我正在使用Spark(通過pyspark)版本1.6.3 (關聯的Python版本2.6.6 )。 我運行一個pyspark shell實例,該實例自動將HiveContext初始化為sqlContext

我想用window函數進行滾動。 我的問題是窗框不是固定的:它取決於我們考慮的觀察結果。 更具體地說,我對變量$ x + 1 $和$ 2x-1 $之間的任何索引為$ x $的觀測值通過名為rank_id的變量進行rank_id並希望進行滾動總和。 因此,我的rangeBetween必須取決於rank_id變量值。

重要的一點是我不想收集數據,因此不能使用諸如numpy東西(我的數據有很多觀察結果)。

可復制的例子

from pyspark.mllib.random import RandomRDDs
import pyspark.sql.functions as psf
from pyspark.sql.window import Window

# Reproducible example
data = RandomRDDs.uniformVectorRDD(sc, 15, 2)
df = data.map(lambda l: (float(l[0]), float(l[1]))).toDF()
df = df.selectExpr("_1 as x", "_2 as y")

#df.show(2)
#+-------------------+------------------+                                        
#|                  x|                 y|
#+-------------------+------------------+
#|0.32767742062486405|0.2506351566289311|
#| 0.7245348534550357| 0.597929853274274|
#+-------------------+------------------+
#only showing top 2 rows

# Finalize dataframe creation
w = Window().orderBy("x")
df = df.withColumn("rank_id", psf.rowNumber().over(w)).sort("rank_id")
#df.show(3)
#+--------------------+--------------------+-------+                             
#|                   x|                   y|rank_id|
#+--------------------+--------------------+-------+
#|0.016536160706045577|0.009892450530381458|      1|
#| 0.10943843181953838|  0.6478505849227775|      2|
#| 0.13916818312857027| 0.24165348228464578|      3|
#+--------------------+--------------------+-------+
#only showing top 3 rows

固定寬度累計總和:沒問題

使用window函數,我可以對給定數量的索引運行累加和(我在這里使用rangeBetween但是對於本示例, rowBetween可以無差別地使用)。

w = Window.orderBy('rank_id').rangeBetween(-1,3)
df1 = df.select('*', psf.sum(df['y']).over(w).alias('roll1'))
#df1.show(3)
#+--------------------+--------------------+-------+------------------+          
#|                   x|                   y|rank_id|             roll1|
#+--------------------+--------------------+-------+------------------+
#|0.016536160706045577|0.009892450530381458|      1|0.9698521852602887|
#| 0.10943843181953838|  0.6478505849227775|      2|1.5744700156326066|
#| 0.13916818312857027| 0.24165348228464578|      3|2.3040547273760392|
#+--------------------+--------------------+-------+------------------+
#only showing top 3 rows

累計總和寬度不固定

我想在索引x + 12x-1之間求和,其中x是我的行索引。 當我嘗試將其傳遞給Spark時(以類似於我們為orderBy所做的方式,也許就是問題所在),我遇到了以下錯誤

# Now if I want to make rangeBetween size depend on a variable
w = Window.orderBy('rank_id').rangeBetween('rank_id'+1,2*'rank_id'-1)

追溯(最近一次調用最近):TypeError中的文件“”,第1行,無法連接“ str”和“ int”對象

我嘗試使用SQL語句進行其他操作

# Using SQL expression
df.registerTempTable('tempdf')
df2 = sqlContext.sql("""
   SELECT *, SUM(y)
   OVER (ORDER BY rank_id
   RANGE BETWEEN rank_id+1 AND 2*rank_id-1) AS cumsum
   FROM tempdf;
""")

這一次給我以下錯誤

追溯(最近一次調用最近):文件“”,行6,在文件“ /opt/application/Spark/current/python/pyspark/sql/context.py”中,行> 580,在sql中返回DataFrame(self._ssql_ctx .sql(sqlQuery),self)文件“ /opt/application/Spark/current/python/lib/py4j-0.9-src.zip/py4j/java_gateway.py”,行813,在調用文件“ / opt / application /裝飾中引發Spark / current / python / pyspark / sql / utils.py“,第51行,引發AnalysisException(s.split(':',1)[1],stackTrace)pyspark.sql.utils.AnalysisException:u”無法在windowframeboundary中識別'rank_id''+''1'附近的輸入;第3行pos 15“

我還注意到,當我嘗試使用SQL OVER子句SQL OVER更簡單的語句時,遇到了類似的錯誤,這可能意味着我沒有將SQL語句正確傳遞給Spark

df2 = sqlContext.sql("""
   SELECT *, SUM(y)
   OVER (ORDER BY rank_id
   RANGE BETWEEN -1 AND 1) AS cumsum
   FROM tempdf;
 """)

追溯(最近一次通話最近):文件“ /opt/application/Spark/current/python/pyspark/sql/context.py”中的文件580行,在SQL中的行580,返回DataFrame(self._ssql_ctx。 sql(sqlQuery),self)文件“ /opt/application/Spark/current/python/lib/py4j-0.9-src.zip/py4j/java_gateway.py”,行813,在調用文件“ / opt / application / Spark”中/current/python/pyspark/sql/utils.py“,第51行,在裝飾中引發AnalysisException(s.split(':',1)[1],stackTrace)pyspark.sql.utils.AnalysisException:u”無法識別在windowframeboundary中的'-''1''AND'附近輸入;第3行pos 15“

如何在Spark中使用windowSQL語句解決問題?

如何在Spark中使用window或SQL語句解決問題?

TL; DR您不能或至少不能以可伸縮的方式滿足當前要求。 您可以嘗試類似於在RDD上滑動的操作: 如何在Pyspark中的時間序列數據上使用滑動窗口轉換數據

我還注意到,當我嘗試使用SQL OVER子句編寫更簡單的語句時,遇到了類似的錯誤,這可能意味着我沒有將SQL語句正確傳遞給Spark

不正確 范圍規范要求( PRECEDING | FOLLOWING | CURRENT_ROW )規范。 也不應有分號:

SELECT *, SUM(x)
OVER (ORDER BY rank_id
RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS cumsum
FROM tempdf

我想在索引x + 1和2x-1之間求和,其中x是我的行索引。 當我嘗試將其傳遞給Spark時(以類似的方式處理orderBy也許就是問題所在),我遇到了以下錯誤...

TypeError:無法連接“ str”和“ int”對象

如異常所示-您不能在字符串和整數上調用+ 您可能想要以下列:

from pyspark.sql.functions import col

.rangeBetween(col('rank_id') + 1,  2* col('rank_id') - 1)

但是不支持。 范圍必須是固定大小,不能根據表達式進行定義。

重要的一點是我不想收集數據

沒有partitionBy窗口定義:

w = Window.orderBy('rank_id').rangeBetween(-1,3)

和收集一樣糟糕。 因此,即使有針對“動態框架”(帶有條件和無邊界窗口)問題的解決方法,它們也無法在這里為您提供幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM