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

如何在PySpark中为多列绘制箱线图?解决大数据量转换报错

解决PySpark大数据集绘制箱线图的内存问题

当PySpark数据集过大时,直接转Pandas会触发内存限制报错,无法直接用PySpark原生绘制箱线图,但可以通过「先在PySpark中计算箱线图所需统计量,再用可视化工具基于统计量绘图」的方式解决,无需全量转换数据。

步骤1:在PySpark中计算箱线图核心统计量

箱线图只需要最小值、Q1(25分位数)、中位数、Q3(75分位数)、最大值,以及基于IQR计算的异常值边界。用PySpark的approxQuantile可以高效计算分位数(大数据集建议设置非0的相对误差提升速度):

from pyspark.sql import functions as F

# 筛选浮点类型数值列
numeric_columns = [col for col, dtype in df.dtypes if dtype.startswith('float')]

# 定义需要计算的分位数点位
quantiles = [0.0, 0.25, 0.5, 0.75, 1.0]

# 逐个列计算箱线图统计量
boxplot_stats = {}
for col in numeric_columns:
    # approxQuantile参数:列名、分位数列表、相对误差(0为精确计算,大数据建议0.01)
    q_vals = df.approxQuantile(col, quantiles, 0.01)
    min_val, q1, median, q3, max_val = q_vals
    iqr = q3 - q1
    # 计算须线边界(异常值判定阈值)
    lower_whisker = max(min_val, q1 - 1.5 * iqr)
    upper_whisker = min(max_val, q3 + 1.5 * iqr)
    
    boxplot_stats[col] = {
        'min': min_val,
        'q1': q1,
        'median': median,
        'q3': q3,
        'max': max_val,
        'lower_whisker': lower_whisker,
        'upper_whisker': upper_whisker
    }

# 转为小体量的Pandas DataFrame,用于后续绘图
import pandas as pd
stats_df = pd.DataFrame(boxplot_stats).T.reset_index().rename(columns={'index': 'column'})

步骤2:基于统计量用Plotly绘制箱线图

用Plotly的go.Box直接传入预计算的统计参数,无需全量数据:

import plotly.graph_objects as go

fig = go.Figure()
# 逐个列添加箱线图轨迹
for _, row in stats_df.iterrows():
    fig.add_trace(go.Box(
        name=row['column'],
        q1=[row['q1']],
        median=[row['median']],
        q3=[row['q3']],
        lowerfence=[row['lower_whisker']],
        upperfence=[row['upper_whisker']],
        y=[row['min'], row['max']]  # 显示数据极值
    ))

fig.update_layout(
    title='PySpark数值列箱线图(基于预计算统计量)',
    yaxis_title='数值',
    boxmode='group'  # 分组显示多列箱线图
)
fig.show()

可选:添加异常值散点

如果需要查看异常值分布,不需要全量导出,可在PySpark中过滤异常值后抽样转Pandas:

outliers_df = pd.DataFrame()
for col in numeric_columns:
    stats = boxplot_stats[col]
    # 筛选当前列的异常值
    col_outliers = df.filter(
        (F.col(col) < stats['lower_whisker']) | (F.col(col) > stats['upper_whisker'])
    )
    # 抽样(按比例或固定条数,避免数据量过大)
    sample_outliers = col_outliers.select(col).sample(False, 0.01, seed=42).toPandas()
    sample_outliers['column'] = col
    outliers_df = pd.concat([outliers_df, sample_outliers])

# 将异常值添加到箱线图中
for col in numeric_columns:
    col_outlier_vals = outliers_df[outliers_df['column'] == col][col].dropna().tolist()
    fig.add_trace(go.Scatter(
        x=[col] * len(col_outlier_vals),
        y=col_outlier_vals,
        mode='markers',
        marker=dict(color='red', size=4),
        showlegend=False
    ))

fig.show()

这种方法只传递统计量和少量抽样数据,完全避开了全量转Pandas的内存限制,适合处理大规模PySpark数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:57:49