如何在 PySpark 中获取多个列的多个百分位数

How do I get multiple percentiles for multiple columns in PySpark

我想获得 10%20%30%... 的百分位数,直到 90% 我的 DataFrame 中的多个列。

我的 DataFrame 是这样设置的:

Col 1 Col 2 Col 3 Col 4 Col 5
250 200 100 50 125
50 10 50 10 10
10 20 20 10 50

(有百万行)

我想要的输出是这样的:

COL | PERCENTILE_10 | PERCENTILE_20 | PERCENTILE_30 | PERCENTILE_40 | PERCENTILE_50 | PERCENTILE_60 | PERCENTILE_70 | PERCENTILE_80 | PERCENTILE_90
col1| 25            |       35      |       45      |      55       |     69        | 100           |   150         |   190         |   250         
col2| 26            |       38      |       42      |      50       |     62        | 102           |   153         |   186         |   220     
col3| 27            |       42      |       46      |      54       |     60        | 104           |   156         |   194         |   260     
col4| 28            |       59      |       70      |      72       |     80        | 106           |   159         |   190         |   290     
col5| 40            |       60      |       89      |      93       |     100       | 108           |   162         |   200         |   300     

您可以遍历每一列以使用 percentile or percentile_approx 函数计算百分位数,然后合并生成的 dfs :

from functools import reduce

import pyspark.sql.functions as F
from pyspark.sql import DataFrame

percentiles_dfs = []

for c in df.columns:
    df1 = df.groupBy(F.lit(c).alias("COL")).agg(*[
        F.expr(f"int(percentile({c}, {i * 0.1}))").alias(f"PERCENTILE_{i}0")
        for i in range(1, 10)
    ])

    percentiles_dfs.append(df1)

result_df = reduce(DataFrame.union, percentiles_dfs)

result_df.show()

#+----+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
#| COL|PERCENTILE_10|PERCENTILE_20|PERCENTILE_30|PERCENTILE_40|PERCENTILE_50|PERCENTILE_60|PERCENTILE_70|PERCENTILE_80|PERCENTILE_90|
#+----+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
#|col1|           18|           26|           34|           42|           50|           89|          129|          170|          210|
#|col2|           12|           14|           16|           18|           20|           55|           91|          128|          164|
#|col3|           26|           32|           38|           44|           50|           60|           70|           80|           90|
#|col4|           10|           10|           10|           10|           10|           18|           25|           34|           42|
#|col5|           18|           26|           34|           42|           50|           65|           79|           95|          110|
#+----+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+