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

Python Plotly Polar Plot 自定义theta轴数据排列顺序问题

解决方案

核心原因是Plotly默认按字符串字典序排列极坐标圆周的theta轴,不会自动识别你要的自定义顺序,你之前写的sorted(['PT'])只是对字符串'PT'做排序,不会作用到数据列,所以不生效。

具体修改步骤

  1. 先修正你原代码的笔误:你定义了分类前缀options,后续all_options拼接时误用了未定义的incompletes,直接替换为options即可。
  2. 将统计后的数据中PT列设置为有序分类类型,指定分类顺序为你需要的自定义序列,Plotly会自动遵循该顺序排布圆周轴。
  3. 额外配置极坐标参数,保证NOT_VISIBLE出现在极坐标顶端,且排序方向为顺时针。

完整可运行代码

import plotly as pt
import plotly.express as px
import pandas as pd
import numpy as np

# 读入数据(你提供的测试数据可以直接赋值给df,实际使用替换为读csv即可)
df = pd.DataFrame({'IDENT': {0L: 'ID76', 1L: 'ID34', 2L: 'ID51', 3L: 'ID97', 4L: 'ID73', 5L: 'ID14', 6L: 'ID64', 7L: 'ID10', 8L: 'ID32', 9L: 'ID89', 10L: 'ID27', 11L: 'ID19', 12L: 'ID80', 13L: 'ID71', 14L: 'ID08', 15L: 'ID47', 16L: 'ID66', 17L: 'ID23'}, 'AGE': {0L: 'YES', 1L: 'NO', 2L: 'YES', 3L: 'NO', 4L: 'NO', 5L: 'NO', 6L: 'YES', 7L: 'YES', 8L: 'YES', 9L: 'NO', 10L: 'YES', 11L: 'YES', 12L: 'NO', 13L: 'YES', 14L: 'NO', 15L: 'NO', 16L: 'YES', 17L: 'YES'}, 'MONTH': {0L: 1990L, 1L: 2000L, 2L: 2010L, 3L: 2020L, 4L: 2020L, 5L: 2010L, 6L: 2000L, 7L: 1990L, 8L: 2020L, 9L: 2010L, 10L: 1990L, 11L: 2020L, 12L: 2000L, 13L: 2010L, 14L: 1990L, 15L: 2020L, 16L: 2000L, 17L: 1990L}, 'LOCATION': {0L: 'E1', 1L: 'E4', 2L: 'E2', 3L: 'E1', 4L: 'E3', 5L: 'E4', 6L: 'E3', 7L: 'E1', 8L: 'E2', 9L: 'E1', 10L: 'E2', 11L: 'E3', 12L: 'E2', 13L: 'E1', 14L: 'E4', 15L: 'E3', 16L: 'E4', 17L: 'E2'}, 'PT5': {0L: np.nan, 1L: 'ABOVE_LIMIT', 2L: np.nan, 3L: np.nan, 4L: np.nan, 5L: np.nan, 6L: np.nan, 7L: np.nan, 8L: '100', 9L: np.nan, 10L: np.nan, 11L: np.nan, 12L: 'NOT_POSSIBLE', 13L: np.nan, 14L: np.nan, 15L: np.nan, 16L: '165', 17L: 'NOT_POSSIBLE'}, 'PT4': {0L: '110', 1L: np.nan, 2L: '145', 3L: np.nan, 4L: 'NOT_VISIBLE', 5L: np.nan, 6L: '105', 7L: np.nan, 8L: np.nan, 9L: np.nan, 10L: 'ABOVE_LIMIT', 11L: np.nan, 12L: np.nan, 13L: np.nan, 14L: 'NOT_VISIBLE', 15L: np.nan, 16L: np.nan, 17L: '130'}, 'PT3': {0L: np.nan, 1L: 'NOT_POSSIBLE', 2L: np.nan, 3L: np.nan, 4L: np.nan, 5L: np.nan, 6L: np.nan, 7L: 'NOT_POSSIBLE', 8L: np.nan, 9L: np.nan, 10L: np.nan, 11L: 'NOT_VISIBLE', 12L: np.nan, 13L: np.nan, 14L: np.nan, 15L: np.nan, 16L: np.nan, 17L: np.nan}, 'PT2': {0L: np.nan, 1L: np.nan, 2L: np.nan, 3L: '160', 4L: np.nan, 5L: np.nan, 6L: np.nan, 7L: '180', 8L: 'NOT_VISIBLE', 9L: np.nan, 10L: '160', 11L: np.nan, 12L: np.nan, 13L: np.nan, 14L: np.nan, 15L: np.nan, 16L: np.nan, 17L: 'ABOVE_LIMIT'}, 'PT1': {0L: np.nan, 1L: np.nan, 2L: np.nan, 3L: np.nan, 4L: 'ABOVE_LIMIT', 5L: np.nan, 6L: np.nan, 7L: np.nan, 8L: np.nan, 9L: np.nan, 10L: np.nan, 11L: np.nan, 12L: '115', 13L: np.nan, 14L: np.nan, 15L: np.nan, 16L: np.nan, 17L: np.nan}})
# 实际使用替换为下面读csv的代码
# df = pd.read_csv('newdata.csv')

# 定义自定义分类顺序
range_num = list(range(100,181, 5))
options = ['NOT_VISIBLE', 'NOT_POSSIBLE', 'ABOVE_LIMIT']
all_options = options + ([str(num) for num in range_num])

# 提取PT值的逻辑和你原有一致
dfnew = df.drop(['IDENT', 'LOCATION', 'MONTH', 'AGE'], axis = 1)
df['PT'] = dfnew.ffill(axis='columns').iloc[:, -1]
data = df.groupby('AGE')['PT'].value_counts().reset_index(name='COUNT')

# 核心修改:将PT列设为有序分类,指定顺序为你定义的all_options
data['PT'] = pd.Categorical(data['PT'], categories=all_options, ordered=True)
# 按分类顺序排序,保证Plotly读取到正确的顺序
data = data.sort_values('PT')

# 绘制极坐标图
fig = px.line_polar(data, r="COUNT", theta="PT", color="AGE", line_close=True,
                    color_discrete_sequence=px.colors.sequential.Plasma_r)

# 配置极坐标:顺时针排布,0度(第一个分类)在顶端
fig.update_layout(
    polar = dict(
        angularaxis = dict(
            direction = "clockwise",
            rotation = 90
        )
    )
)

fig.show()

效果说明

运行后极坐标圆周会严格按照你要求的顺序排列:顶端为NOT_VISIBLE,顺时针依次是NOT_POSSIBLE、ABOVE_LIMIT,之后按100、105、110……180升序排列,同时保留按AGE分组的两条线的对比效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 12:27:00