Seaborn箱线图异常:添加类别后原有箱线图被改写求助
解决箱线图添加类别后原有图形变形的问题
我尝试基于不同气旋类型(V0_V1、V1、V0_V2_12、V2_12)绘制Na浓度的箱线图,但加入V0_V2_12、V2_12类别后,原有V0_V1、V1的箱线图发生变化,疑似被改写。代码如下:
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # Load Excel file file_path = 'XRF Co-locations.xlsx' # file name sheet = "Masterlist Co-locations" # sheet I want to isolate df_dict = pd.read_excel(file_path, sheet_name=[sheet], header=2) # put into dictionary df = df_dict[sheet] # Clean column names df.columns = df.columns.str.strip() # get rid of white spaces # Filter based on Notes v0_v1_na = df[df["Notes"] == "V0_V1"]["Na (ng/cm2)"] v1_na = df[df["Notes_2"] == "V1"]["Na (ng/cm2)_2"] v0_v2_12_na = df[df["Notes"] == "V0_V2_12"]["Na (ng/cm2)"] v2_12_na = df[df["Notes_2"] == "V2_12"]["Na (ng/cm2)_2"] # Combine into DataFrames and compute median for each df_mean_v0 = v0_na.median() # calculate the median of v0_na df_mean_v1 = v1_na.median() # calculate the median of v1_na df_mean_v0_v2_12 = v0_v2_12_na.median() # calculate the median of Na for v0_v2_12 df_mean_v2_12 = v2_12_na.median() # calculate the median of Na for v2_12 print(df_mean_v0) print(df_mean_v1) print(df_mean_v0_v2_12) print(df_mean_v2_12) # Plot plt.figure(figsize=(12, 6)) # Create boxplots for v0_na and v1_na side by side sns.boxplot(data=[v0_na, v1_na, v0_v2_12_na, v2_12_na], orient="v", palette="husl") # Adding labels, title, and customization plt.ylabel("Na Concentration (ng/cm²)", fontsize=12) plt.xlabel("Cyclone Type", fontsize=12) plt.xticks([0, 1, 2, 3], ['V0_V1', 'V1', 'V0_V2_12', 'V2_12'], rotation=0) # Custom x-ticks for the two categories plt.title("Box Plot of Na (ng/cm²) for V0 and V1 Cyclones", fontsize=14) plt.legend() plt.show()
问题分析与修复步骤
1. 修正变量名错误
代码存在未定义变量问题:你定义了v0_v1_na,但后续计算中位数和绘图时误用了v0_na,这会直接报错,也可能干扰你对数据是否被改写的判断。先把所有v0_na替换为v0_v1_na。
2. 重构为长格式DataFrame
当前用列表传入多个Series给sns.boxplot的方式,容易因不同类别数据范围差异导致坐标轴自动缩放,让原有箱线图视觉上“变形”(实际数据未修改,仅坐标轴范围变化)。改用长格式DataFrame能更清晰管理数据,避免这类问题:
# 重构为长格式数据 data_list = [] # 添加各类型数据(过滤空值) data_list.extend([("V0_V1", val) for val in v0_v1_na.dropna()]) data_list.extend([("V1", val) for val in v1_na.dropna()]) data_list.extend([("V0_V2_12", val) for val in v0_v2_12_na.dropna()]) data_list.extend([("V2_12", val) for val in v2_12_na.dropna()]) # 转为标准DataFrame plot_df = pd.DataFrame(data_list, columns=["Cyclone Type", "Na Concentration (ng/cm²)"]) # 绘制箱线图 plt.figure(figsize=(12, 6)) sns.boxplot(data=plot_df, x="Cyclone Type", y="Na Concentration (ng/cm²)", palette="husl") plt.title("Box Plot of Na (ng/cm²) by Cyclone Type", fontsize=14) plt.show()
3. 验证数据未被改写
先单独打印V0_V1和V1的统计量,确认添加新类别前后数据无变化:
# 打印V0_V1统计信息 print("V0_V1 统计量:") print(v0_v1_na.describe()) # 打印V1统计信息 print("\nV1 统计量:") print(v1_na.describe())
如果中位数、四分位数等统计量与之前一致,说明数据未被改写,只是坐标轴缩放导致视觉变化。
4. 手动控制坐标轴范围(可选)
若新类别数据范围远大于原有类别,可手动设置y轴范围,保持原有箱线图的视觉比例:
plt.ylim(0, 自定义最大值)
内容的提问来源于stack exchange,提问作者Kathryn Cheng
相关产品推荐
相关产品推荐

