如何计算Spark中过去时间值的`percent_rank`?

时间:2017-08-23 08:41:44

标签: apache-spark pyspark

我想计算列percent_rank的{​​{1}},但排名应仅相对于过去的值 - 由时间戳变量{{确定1}}。

似乎x不接受任何参数,并且让排名与时间无关t?!

有没有办法根据较小的时间戳的值来获得排名?

预期结果类似于

F.percent_rank()

2 个答案:

答案 0 :(得分:1)

为了获得滚动percent_rank(),您必须能够使用窗口框架定义来排序您根本无法进行的功能。 (像这样w = Window.orderBy('t', 'x').rowsBetween(-sys.maxsize, 0)

我找到了解决方法,但它涉及笛卡尔联合,这是非常昂贵的:

 

首先让我们创建示例数据框:

import pyspark.sql.functions as psf
from pyspark.sql import HiveContext
hc = HiveContext(sc)
df = hc.createDataFrame(sc.parallelize(zip(range(5), [1,3,5,4,2])), ['t', 'x'])

笛卡尔联盟:

df2 = df.groupBy(df.x.alias('x2')).agg(psf.min("t").alias("t2"))
df_cross = df.join(df2).filter("t2 <= t").withColumn("isSup", (df.x > df2.x2).cast("int"))

    +---+---+---+---+-----+
    |  t|  x| t2| x2|isSup|
    +---+---+---+---+-----+
    |  1|  3|  0|  1|    1|
    |  2|  5|  0|  1|    1|
    |  2|  5|  1|  3|    1|
    |  3|  4|  0|  1|    1|
    |  3|  4|  1|  3|    1|
    |  3|  4|  2|  5|    0|
    |  4|  2|  0|  1|    1|
    |  4|  2|  1|  3|    0|
    |  4|  2|  2|  5|    0|
    |  4|  2|  3|  4|    0|
    +---+---+---+---+-----+

最后我们按't'分组,'x':

df_fin = df_cross.groupBy("t", "x").agg(
    psf.count("*").alias("count"), 
    psf.sum("isSup").alias("rank")
).withColumn('pct_rank_win', psf.col("rank")/psf.greatest(psf.col('count') - 1, psf.lit(1)))

    +---+---+-----+----+------------------+
    |  t|  x|count|rank|      pct_rank_win|
    +---+---+-----+----+------------------+
    |  0|  1|    1|   0|               0.0|
    |  1|  3|    2|   1|               1.0|
    |  2|  5|    3|   2|               1.0|
    |  3|  4|    4|   2|0.6666666666666666|
    |  4|  2|    5|   1|              0.25|
    +---+---+-----+----+------------------+

groupBy('x')定义中的df2是为了确保密集排名(相同的值具有相同的排名),如下例所示:

df = hc.createDataFrame(sc.parallelize(zip(range(6), [1,3,3,5,4,2])), ['t', 'x'])

    +---+---+-----+----+------------------+
    |  t|  x|count|rank|      pct_rank_win|
    +---+---+-----+----+------------------+
    |  0|  1|    1|   0|               0.0|
    |  1|  3|    2|   1|               1.0|
    |  2|  3|    2|   1|               1.0|
    |  3|  5|    3|   2|               1.0|
    |  4|  4|    4|   2|0.6666666666666666|
    |  5|  2|    5|   1|              0.25|
    +---+---+-----+----+------------------+

答案 1 :(得分:1)

这是我尝试在窗口分区上使用collect_set的另一项工作,

{{1}}