PySpark计算各列最大百分比变化及对应发生年份
需求实现:获取DataFrame各列最大百分比变化值及对应年份
原PySpark代码
# 透视后重命名列 new_column_names = ["Year"] + [col_name.replace(" ", "_") for col_name in pivot_table.columns[1:]] pivot_table = pivot_table.toDF(*new_column_names) # 任务4:计算百分比变化 percentage_cols = pivot_table.columns[1:] # 排除"Year"列 window_spec = Window.orderBy("Year") print(pivot_table.columns) pivot_table = pivot_table.drop('Other_purchases_and_operating_expenses') # 循环计算百分比变化 for col_name in percentage_cols: pivot_table = pivot_table.withColumn(f"{col_name}_lag", lag(col(col_name)).over(window_spec)) pivot_table = pivot_table.withColumn(f"{col_name}_change", (col(col_name) - col(f"{col_name}_lag")) / col(f"{col_name}_lag") * 100) pivot_table = pivot_table.drop(f"{col_name}_lag") pivot_table = pivot_table.drop(f"{col_name}")
原代码输出
year column ,variablenames column 3
实现方案
基于现有代码的输出结果,我们可以通过窗口函数和聚合操作,快速获取每列的最大百分比变化值及对应年份,具体代码如下:
from pyspark.sql import functions as F from pyspark.sql.window import Window # 收集所有百分比变化列(列名以_change结尾) change_cols = [col for col in pivot_table.columns if col.endswith("_change")] # 构建聚合表达式:同时获取每个变化列的最大值和对应年份 agg_exprs = [] for col in change_cols: # 计算当前列的最大百分比变化值 max_change = F.max(col).alias(f"max_{col}") # 获取该最大值对应的年份(按变化值降序取第一行的年份) corresponding_year = F.first("Year", ignorenulls=True).over( Window.partitionBy().orderBy(F.desc(col)) ).alias(f"year_of_max_{col}") agg_exprs.extend([max_change, corresponding_year]) # 执行聚合并获取结果 max_change_result = pivot_table.select(*agg_exprs).limit(1) # 展示最终结果 max_change_result.show(truncate=False)
代码说明
- 筛选变化列:通过列名后缀
_change识别所有百分比变化字段,避免手动指定列名。 - 聚合逻辑:
- 用
F.max()计算每列的最大百分比变化值,并重命名字段以明确含义。 - 全局窗口按变化值降序排序,取第一行的年份作为最大值对应的发生年份;
ignorenulls=True会自动跳过空值行(比如第一年无对比数据生成的null)。
- 用
- 结果输出:
limit(1)确保只返回一行全局聚合结果,show(truncate=False)避免年份或数值被截断。
补充说明
如果某列存在多个年份有相同的最大百分比变化值,上述代码会返回最早出现的年份。若要获取所有对应年份,可将first替换为collect_list,示例如下:
corresponding_year = F.collect_list("Year").over( Window.partitionBy().orderBy(F.desc(col)) ).alias(f"years_of_max_{col}")
内容的提问来源于stack exchange,提问作者sara ali khan
相关产品推荐
相关产品推荐

