You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PySpark中按组标准化DataFrame所有列?

如何在PySpark中按组对DataFrame所有列执行min-max标准化?

嘿,我懂你想要复刻Pandas里那种按组对所有列做min-max标准化的操作,PySpark的API逻辑和Pandas不太一样,咱们得换个方式实现,下面是完整的解决方案:

步骤1:创建示例DataFrame

先把你给的示例数据转换成PySpark DataFrame,方便后续测试:

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

spark = SparkSession.builder.appName("GroupNormalization").getOrCreate()

# 定义列名和数据
columns = ['group', 'sensor1', 'sensor2', 'sensor3']
vals = [ 
    ("a", 0.8, 0.02, 100), 
    ("a", 0.5, 0.1, 200), 
    ("a", 1, 0.5, 50), 
    ("a", 0, 0.8, 30),
    ("b", 10, 1, 0),
    ("b", 20, 2, 3),
    ("b", 5, 4, 1) 
]

df = spark.createDataFrame(vals, columns)
df.show()

步骤2:计算每个组的min和max值

我们需要先按group分组,计算每个数值列的最小值和最大值,然后把这些统计量和原DataFrame关联起来:

# 获取所有需要标准化的数值列(排除group列)
num_cols = [col for col in columns if col != 'group']

# 生成每个列的min和max聚合表达式
agg_exprs = []
for col in num_cols:
    agg_exprs.append(F.min(col).alias(f"{col}_min"))
    agg_exprs.append(F.max(col).alias(f"{col}_max"))

# 计算每个组的min/max并和原表join
group_stats = df.groupBy("group").agg(*agg_exprs)
df_with_stats = df.join(group_stats, on="group", how="inner")

步骤3:执行min-max标准化

接下来对每个数值列应用标准化公式(x - x_min)/(x_max - x_min),同时要处理x_max等于x_min的情况(避免除以零报错),最后填充空值为0:

norm_cols = []
for col in num_cols:
    # 计算标准化值,处理除以零的情况
    norm_col = F.when(
        F.col(f"{col}_max") != F.col(f"{col}_min"),
        (F.col(col) - F.col(f"{col}_min")) / (F.col(f"{col}_max") - F.col(f"{col}_min"))
    ).otherwise(0.0).alias(col)
    norm_cols.append(norm_col)

# 组合结果:保留group列,加上标准化后的数值列
df_norm = df_with_stats.select("group", *norm_cols).fillna(0)

查看结果

运行完上面的代码后,查看最终的标准化结果:

df_norm.show(truncate=False)

输出结果和你期望的一致,比如group 'a'的sensor1列,0.8对应的标准化值是(0.8-0)/(1-0)=0.8,sensor3列的200对应(200-30)/(200-30)=1,完全符合预期。

简化写法(可选)

如果你觉得上面的循环有点繁琐,也可以用列表推导式简化:

num_cols = [col for col in columns if col != 'group']

group_stats = df.groupBy("group").agg(
    *[F.min(c).alias(f"{c}_min") for c in num_cols],
    *[F.max(c).alias(f"{c}_max") for c in num_cols]
)

df_norm = df.join(group_stats, on="group") \
    .select(
        "group",
        *[
            F.when(
                F.col(f"{c}_max") != F.col(f"{c}_min"),
                (F.col(c) - F.col(f"{c}_min")) / (F.col(f"{c}_max") - F.col(f"{c}_min"))
            ).otherwise(0.0).alias(c)
            for c in num_cols
        ]
    ).fillna(0)

这个方法的核心是先预计算每组的统计量,再通过关联表把统计量带到每一行,最后逐列计算标准化值,完美对应你Pandas代码里的groupby.transform逻辑。

内容的提问来源于stack exchange,提问作者LN_P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:40:16