Python象限图中心十字线绘制异常问题的修复咨询
象限图中心十字线异常修复方案
问题描述
我编写了如下Python代码用于生成象限图,但图表的中心十字线位置不正确,需要修复。
原代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt import plotly.express as px import plotly.graph_objects as go import seaborn as sns # 数据准备 data = pd.DataFrame({ 'label': ['Luis', 'Sara', 'Jeroen', 'Sophie', 'Florence', 'Simeon', 'Lambert', 'Rahul', 'Peter', 'John'], 'Data Culture': [0, 5, 10, 15, 20, 18, 13, 9, 4, 1], 'Data Skills': [20, 15, 10, 5, 0, 3, 7, 11, 16, 18] }) print(data) fig = px.scatter(data, x=data["Data Culture"], y=data["Data Skills"], text=data.label, title='Data Culture vs Data Skills', width=800, height=600) # 计算平均值 x_avg = data['Data Culture'].mean() y_avg = data['Data Skills'].mean() # 添加横竖线(原代码问题所在) fig.add_vline(x=10, line_width=3, opacity=0.5) fig.add_hline(y=10, line_width=3, opacity=0.5) # 设置X轴范围 adj_x = max((data['Data Culture'].max() - x_avg), (x_avg - data['Data Culture'].min())) * 1.1 lb_x, ub_x = (x_avg - adj_x, x_avg + adj_x) fig.update_xaxes(range = [lb_x, ub_x]) # 设置Y轴范围 adj_y = max((data['Data Skills'].max() - y_avg), (y_avg - data['Data Skills'].min())) * 1.1 lb_y, ub_y = (y_avg - adj_y, y_avg + adj_y) fig.update_yaxes(range = [lb_y, ub_y]) # 更新X轴刻度标签 axis = ['Low', 'High'] fig.update_layout( xaxis_title='Data Culture', xaxis = dict( tickmode = 'array', tickvals = ([(x_avg - adj_x / 2), (x_avg + adj_x / 2)]), ticktext = axis ) ) # 更新Y轴刻度标签 fig.update_layout( yaxis_title='Data Skills', yaxis = dict( tickmode = 'array', tickvals = ([(y_avg - adj_y / 2), (y_avg + adj_y / 2)]), ticktext = axis, tickangle=270 ) ) # 更新标题和边距(原代码有重复设置) fig.update_layout(margin=dict(t=50, l=5, r=5, b=50), title={'text': 'pl', 'font_size': 20, 'y':1.0, 'x':0.5, 'xanchor': 'center', 'yanchor': 'top'}) # 添加象限标注 fig.add_annotation(dict(font=dict(color="black",size=18), x=0, y=-0.15, text="Han Solo", xref='paper', yref='paper', showarrow=False)) fig.add_annotation(dict(font=dict(color="black",size=18), x=1, y=-0.15, text="Young Padawan", xref='paper', yref='paper', showarrow=False)) fig.add_annotation(dict(font=dict(color="black",size=18), x=0, y=1.15, text="Baby Yoda", xref='paper', yref='paper', showarrow=False)) fig.add_annotation(dict(font=dict(color="black",size=18), x=1, y=1.15, text="Yoda", xref='paper', yref='paper', showarrow=False)) fig.update_layout( margin=dict(l=20, r=20, t=100, b=100), ) fig.show()
版本信息
import pandas as pd import numpy as np import matplotlib import plotly import seaborn as sns print("Pandas: ", pd.__version__) print("numpy: ", np.__version__) print("matplotlib: ",matplotlib.__version__) print("seaborn: ", sns.__version__) print("Plotly: ",plotly.__version__) # 输出结果 Pandas: 1.1.5 numpy: 1.21.6 matplotlib: 3.2.1 seaborn: 0.11.2 Plotly: 5.10.0
问题原因
原代码中绘制十字线时使用了固定值x=10和y=10,但后续代码是基于数据的平均值x_avg和y_avg调整坐标轴范围的,导致十字线与坐标轴中心不重合。
修复方案
将绘制横竖线的固定值替换为计算出的平均值x_avg和y_avg,同时合并重复的布局设置优化代码结构:
修改后的核心代码片段
# 计算平均值 x_avg = data['Data Culture'].mean() y_avg = data['Data Skills'].mean() # 添加居中的横竖线(修复后) fig.add_vline(x=x_avg, line_width=3, opacity=0.5) fig.add_hline(y=y_avg, line_width=3, opacity=0.5)
完整修复后代码
import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go # 数据准备 data = pd.DataFrame({ 'label': ['Luis', 'Sara', 'Jeroen', 'Sophie', 'Florence', 'Simeon', 'Lambert', 'Rahul', 'Peter', 'John'], 'Data Culture': [0, 5, 10, 15, 20, 18, 13, 9, 4, 1], 'Data Skills': [20, 15, 10, 5, 0, 3, 7, 11, 16, 18] }) fig = px.scatter(data, x="Data Culture", y="Data Skills", text="label", width=800, height=600) # 计算平均值 x_avg = data['Data Culture'].mean() y_avg = data['Data Skills'].mean() # 添加居中的十字线 fig.add_vline(x=x_avg, line_width=3, opacity=0.5) fig.add_hline(y=y_avg, line_width=3, opacity=0.5) # 设置X轴范围 adj_x = max((data['Data Culture'].max() - x_avg), (x_avg - data['Data Culture'].min())) * 1.1 lb_x, ub_x = (x_avg - adj_x, x_avg + adj_x) fig.update_xaxes(range=[lb_x, ub_x]) # 设置Y轴范围 adj_y = max((data['Data Skills'].max() - y_avg), (y_avg - data['Data Skills'].min())) * 1.1 lb_y, ub_y = (y_avg - adj_y, y_avg + adj_y) fig.update_yaxes(range=[lb_y, ub_y]) # 更新坐标轴标签与刻度 axis_labels = ['Low', 'High'] fig.update_layout( xaxis_title='Data Culture', xaxis=dict( tickmode='array', tickvals=[x_avg - adj_x/2, x_avg + adj_x/2], ticktext=axis_labels ), yaxis_title='Data Skills', yaxis=dict( tickmode='array', tickvals=[y_avg - adj_y/2, y_avg + adj_y/2], ticktext=axis_labels, tickangle=270 ), # 统一设置边距和标题 margin=dict(t=100, l=20, r=20, b=100), title={ 'text': 'Data Culture vs Data Skills', 'font_size': 20, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top' } ) # 添加象限标注 fig.add_annotation( font=dict(color="black", size=18), x=0, y=-0.15, text="Han Solo", xref='paper', yref='paper', showarrow=False ) fig.add_annotation( font=dict(color="black", size=18), x=1, y=-0.15, text="Young Padawan", xref='paper', yref='paper', showarrow=False ) fig.add_annotation( font=dict(color="black", size=18), x=0, y=1.15, text="Baby Yoda", xref='paper', yref='paper', showarrow=False ) fig.add_annotation( font=dict(color="black", size=18), x=1, y=1.15, text="Yoda", xref='paper', yref='paper', showarrow=False ) fig.show()
修复效果
修改后,十字线会准确对齐坐标轴的中心(即数据平均值位置),与后续基于平均值调整的坐标轴范围完全匹配,解决了十字线偏移的问题。
内容的提问来源于stack exchange,提问作者Luis Valencia
相关产品推荐
相关产品推荐

