Python Plotly Polar Plot 自定义theta轴数据排列顺序问题
解决方案
核心原因是Plotly默认按字符串字典序排列极坐标圆周的theta轴,不会自动识别你要的自定义顺序,你之前写的sorted(['PT'])只是对字符串'PT'做排序,不会作用到数据列,所以不生效。
具体修改步骤
- 先修正你原代码的笔误:你定义了分类前缀
options,后续all_options拼接时误用了未定义的incompletes,直接替换为options即可。 - 将统计后的数据中
PT列设置为有序分类类型,指定分类顺序为你需要的自定义序列,Plotly会自动遵循该顺序排布圆周轴。 - 额外配置极坐标参数,保证
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
相关产品推荐
相关产品推荐

