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

如何在含分位数分组分类值的散点图中保留轴顺序?

如何在散点图中保留分位数区间的轴顺序

这个问题我之前也碰到过!核心原因是你把Categorical类型的区间直接转成字符串后,matplotlib会把它们当成无序的文本值来排序,自然就乱了。其实我们可以利用pandas qcut生成的区间本身带有的顺序来解决这个问题,给你两个实用的方案:

方案一:利用Categorical的内置顺序(推荐)

pd.qcut生成的x_group和y_group本质是Categorical类型,它们自带了区间从小到大的顺序。我们可以用这些类别的整数编码作为散点图的坐标,之后再把轴刻度替换成对应的区间字符串,这样既保证了顺序,又能显示正确的文本。

修改后的完整代码如下:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np

n_tile = 5
np.random.seed(0)
x = np.random.normal(150, 70, 3000,)
y = np.random.normal(1, 0.3, 3000)
r = np.random.normal(0.4, 0.1, 3000)

plot_data = pd.DataFrame({ 'x': x, 'y': y, 'r': r })
# qcut生成的是Categorical类型,自带顺序
plot_data['x_group'] = pd.qcut(plot_data['x'], n_tile, duplicates='drop')
plot_data['y_group'] = pd.qcut(plot_data['y'], n_tile, duplicates='drop')

plot_data_grouped = plot_data.groupby(['x_group','y_group'], as_index=False).agg({'r':['mean','count']})
plot_data_grouped.columns = ['x','y','mean','count']

plt.figure(figsize=(10,10))

# 关键:用类别编码作为散点的坐标,保证顺序
x_codes = plot_data_grouped['x'].cat.codes
y_codes = plot_data_grouped['y'].cat.codes

scatter = plt.scatter(
    x=x_codes, 
    y=y_codes, 
    s=plot_data_grouped["count"], 
    c=plot_data_grouped['mean'], 
    cmap="RdYlGn", 
    edgecolors="black"
)

# 替换轴刻度为区间字符串
x_categories = plot_data['x_group'].cat.categories
y_categories = plot_data['y_group'].cat.categories

plt.xticks(ticks=np.arange(len(x_categories)), labels=x_categories, rotation=45)
plt.yticks(ticks=np.arange(len(y_categories)), labels=y_categories)

# 补充可视化细节
plt.colorbar(scatter, label='Mean of r')
plt.xlabel('X Quantile Intervals')
plt.ylabel('Y Quantile Intervals')
plt.title('Scatter Plot with Ordered Quantile Intervals')
plt.tight_layout()
plt.show()

关键步骤解释:

  1. 保留Categorical类型:不要把x_group/y_group转成字符串,它们本身就存储了区间的顺序信息。
  2. 用类别编码绘图:cat.codes会返回每个区间对应的整数(从0开始,按区间从小到大排序),用这个整数作为散点的x/y坐标,matplotlib就会按顺序排列。
  3. 替换刻度标签:用plt.xticks和plt.yticks把整数刻度替换成对应的区间字符串,这样轴上显示的还是你需要的区间文本,同时顺序完全正确。

方案二:手动指定字符串顺序(兼容已转字符串的场景)

如果你已经把区间转成了字符串,也可以手动提取正确的顺序来设置轴的刻度:

# 假设plot_data_grouped['x']已经是字符串类型
# 从原始的Categorical中获取正确的顺序
x_order = [str(cat) for cat in plot_data['x_group'].cat.categories]
y_order = [str(cat) for cat in plot_data['y_group'].cat.categories]

# 绘图后设置轴的顺序
plt.xticks(ticks=np.arange(len(x_order)), labels=x_order, rotation=45)
plt.yticks(ticks=np.arange(len(y_order)), labels=y_order)

这个方案的核心是从原始的Categorical类别中提取顺序,再强制matplotlib按这个顺序显示刻度。

总结

最优雅的方式是直接利用pandas Categorical类型自带的顺序,避免把区间转成字符串丢失顺序信息。方案一既简洁又能保证可视化的准确性,推荐优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:47:51