在pyspark中计算窗口上列的百分位数
Posted
技术标签:
【中文标题】在pyspark中计算窗口上列的百分位数【英文标题】:calculate percentile of column over window in pyspark 【发布时间】:2020-06-30 06:06:01 【问题描述】:我有一个用例,我需要在滑动窗口上计算列(我们称之为 X)的百分位数。 所以窗口定义是按时间顺序排列的 - 过去 120 天:
days = lambda i: i * 86400
w = Window.partitionBy("entityId").orderBy(F.col("trn_time").cast("long").asc())
.rangeBetween(-days(120),-days(1))
我想过使用 approxQuantile 但它是一个 Dataframe 函数。 第二个选项是使用:
percent_rank().over(w)
但我需要按要在其上进行百分位数的数字列 (X) 对窗口进行排序,并且窗口已经按时间排序。 当我尝试在窗口定义中将 X 添加到 orderBY 时:
w = Window.partitionBy("entityId").orderBy(F.col("trn_time").cast("long").asc(),"X")\
.rangeBetween(-days(120),-days(1))
我收到以下错误:“不能在具有多个 order by 表达式的窗口规范中使用具有值边界的范围窗口框架”
我该如何实现这个逻辑?
【问题讨论】:
您可以尝试使用row_number()
的窗口函数按时间和 X 对 df 进行排序,然后在最终计算中按该行号而不是时间和 X 进行排序
【参考方案1】:
你需要把它写成一个内置的 SQL 表达式:
# This is like a UDF
magic_percentile = F.expr('percentile_approx(X, 0.5)')
# Define your window
w = Window.partitionBy("entityId").orderBy(F.col("trn_time").cast("long").asc())
.rangeBetween(-days(120),-days(1))
df = df.withColumn("rolling_percentile", magic_percentile.over(w))
在计算百分位数时,您总是将值从小到大排序,然后取分位数,这样窗口内的值就会被排序。
参考:Median / quantiles within PySpark groupBy
【讨论】:
感谢@pissall,但是百分位数何时对值进行排序,这是缺少的部分,在您共享的示例中,只需在 X 上执行 percentile_approx ,而不对 X 进行排序。窗口按顺序排序时间。 @user1450410 排序会发生在窗口函数内部,你是看不到的。以上是关于在pyspark中计算窗口上列的百分位数的主要内容,如果未能解决你的问题,请参考以下文章
python使用pandas中的groupby函数和agg函数计算每个分组数据的两个分位数(例如百分之10分位数和百分之90分位数)
Pandas .. 分位数函数是不是需要排序数据来计算百分位数?
如何在 JavaScript(或 PHP)中获取数组的中位数和四分位数/百分位数?