使用QuantileDiscretizer在Pyspark中计算百分位数排名

3

我想知道在pyspark中是否可以使用QuantileDiscretizer转换器来获得percentile_rank的结果。

目的是为了避免在整个列上计算percent_rank,因为这会生成以下错误:

WARN WindowExec: No Partition Defined for Window operation! 
Moving all data to a single partition, this can cause serious performance degradation.

我采用的方法是首先使用 QuantileDiscretizer,然后归一化到 [0,1]:

from pyspark.sql.window import Window
from pyspark.ml.feature import QuantileDiscretizer
from scipy.stats import gamma

X1 = gamma.rvs(0.2, size=1000)

df = spark.createDataFrame(pd.DataFrame(X1, columns=["x"]))

df = df.withColumn("perc_rank", F.percent_rank().over(Window.orderBy("x")))
df = QuantileDiscretizer(numBuckets=df.count()+1,\
                         inputCol="x",\
                         outputCol="q_discretizer").fit(df).transform(df)

agg_values = df.agg(F.max(df["q_discretizer"]).alias("maxval"),\
                    F.min(df["q_discretizer"]).alias("minval")).collect()[0]

xmax, xmin = agg_values.__getitem__("maxval"), agg_values.__getitem__("minval")
normalize = F.udf(lambda x: (x-xmin)/(xmax-xmin))

df = df.withColumn("perc_discretizer", normalize("q_discretizer"))
df = df.withColumn("error", F.round(F.abs(F.col("perc_discretizer")- F.col("perc_rank")),6) )
print(df.select(F.max("error")).show())
df.show(5)

然而,似乎增加数据点的数量会增加误差,所以我不确定这是否是正确的方法。

是否可以使用QuantileDiscretizer来获取百分位数排名?

或者,是否有一种高效的方式可以计算整个列的percentile_rank

1个回答

1

你可以使用以下方法来避免警告信息:

X1 = gamma.rvs(0.2, size=10)
df = spark.createDataFrame(pd.DataFrame(X1, columns=["x"]))
df = df.withColumn("dummyCol", F.lit("some_val"))
win = Window.partitionBy("dummyCol").orderBy("x")
df = df.withColumn("perc_rank", F.percent_rank().over(win)).drop("dummyCol")

但是,数据仍将移动到单个工作器,我认为没有更好的替代方案来避免洗牌,因为需要对完整列进行排名。

如果您在同一列上有多个窗口,则可以尝试预分区数据,然后应用排名函数。


感谢您的建议。尽管如此,这将等同于只有一个分区,除了警告错误之外。无论如何,我认为您预先分区的想法很有趣...而不是使用F.lit("some_val"),可以设置一个分区索引。 - Galuoises
是的,老实说,我认为只有在处理非常大的数据集或资源预算受限时才有用,否则不值得麻烦。 - Abhinav
无论如何,即使我对数据进行分区,问题在于percent_rank仅在每个分区内查找每个百分位数,而它应该在每个分区内查找以正确计算值。 - Galuoises

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接