我有一个数据框df
,其中包括两列:
每个组都有多个元素。
还有其他列,例如SCORE。
我需要:
使用get_bucket_udf
UDF将存储桶分配给GROUP中的每个SCORE。
为每个元素创建结构{'GROUP_ID', 'BUCKET', 'SCORE'}
(SCORE_SET),并将这些结构聚合到每个元素的列表中。
在步骤1之前,我先按GROUP_ID进行分区,因此,步骤1-2仅在3个执行程序上运行,因为我们只有3个GROUP。
在第2步之后,我尝试通过ELEMENT_ID重新分区以利用100个执行器,但是通过查看Hadoop Resource Manager,我发现它仍然仅使用3个执行器。
是否可以利用所有执行者进行步骤3? 代码如下。谢谢!
#Step 1
group_id_partition = Window.partitionBy('GROUP_ID')
group_id_ordered_by_score = df_partition.orderBy('SCORE')
group_id_score_ranked = df.select(
'*',
func.row_number().over(group_id_ordered_by_score).alias('SCORE_RANK'))
group_id_ordered_by_rank = group_id_partition.orderBy('SCORE_RANK')
# Compute cumulative sum for each row within group_id
df_enhanced = group_id_score_ranked.select(
'ELEMENT_ID',
func.sum('SCORE').over(group_id_partition).alias('SCORE_SUM'),
func.sum('SCORE').over(
group_id_ordered_by_rank.rangeBetween(Window.unboundedPreceding, Window.currentRow)
).alias('SCORE_CUMSUM')
).orderBy('ID', 'SCORE')
# Step 2
df_enhanced_bucketed = df_enhanced.select(
'*',
get_bucket_udf('SCORE_SUM', 'SCORE_CUMSUM').alias('BUCKET'))
# Repartition by ELEMENT_ID - does not redistribute over all executors
df_enhanced_bucketed_repartitioned = df_enhanced_bucketed.repartition('ELEMENT_ID')
# Step 3
output_df_structed = df_enhanced_bucketed_repartitioned.select(
'ELEMENT_ID',
func.struct('GROUP_ID', 'BUCKET', 'SCORE').alias('SCORE_SET'))
output_df = output_df_structed.groupBy('ELEMENT_ID').agg(
func.collect_list('SCORE_SET').alias('SCORE_SETS'))
result = output_df.select('ELEMENT_ID', 'SCORE_SETS')
result.take(1)