I have a DataFrame like that:
SCORE = spark.createDataFrame(
[
('a', "Joe", 1),
('b', "Doe", 2),
('c', "Carl", 3),
('d', "CJ", 4),
('e', "Tom", 5),
],
StructType(
[
StructField("id", StringType(), False),
StructField("user", StringType(), False),
StructField("score", IntegerType(), False),
]
)
)
| id | user | score |
|---|---|---|
| a | Joe | 1 |
| b | Doe | 2 |
| c | Carl | 3 |
| d | CJ | 4 |
| e | Tom | 5 |
I have written a UDF to calculate a percentile_score, and it's based on the whole score column. And it's working, is generating a new column called percentile_score:
from pyspark.sql.functions import udf, collect_list
def calculate_percentile(user_score, score_list):
data_prs_score.sort()
scores_count = len(score_list)
cumulative_frequency = 0
frequency = 0
for score in score_list:
if score == user_score:
frequency += 1
elif score > user_score:
break
cumulative_frequency += 1
return (cumulative_frequency - (0.5 * frequency)) / scores_count
def make_score_list(score_list):
return udf(lambda user_score: calculate_percentile(user_score, score_list), FloatType())
SCORE.withColumn('percentile_score', make_prs_score_list(SCORE.select(collect_list('score')).collect()[0][0])(col('score'))).show()
My problem is, this function is taking 1 hour to run.
I think the reason that is taking so long is that I'm using the collect() on the UDF. However, I can't see another way to build that.
So I was wondering what kind of optimization I can do here.