如何使用Matplotlib创建自定义Python项目阶段进度图表
实现定制化项目阶段进度与结果图表
没问题!我来帮你一步步搞定这个定制化图表,用Matplotlib结合Pandas就能完美实现你想要的效果,完全贴合你的需求~
1. 先把数据处理好
首先我们把你给的原始数据整理成Pandas DataFrame,然后筛选出ItemStatus为Complete的项目(毕竟只有完成的项目才有确定的Outcome),再按阶段分组统计每个结果的数量:
import pandas as pd import matplotlib.pyplot as plt # 把你的原始数据转成DataFrame data = { 'ItemID': [1,2,3,4,5,6,7,8], 'ItemPhase': ['Phase1', 'Phase2', 'Phase1', 'Phase3', 'Phase2', 'Phase2', 'Phase3', 'Phase2'], 'ItemStatus': ['Complete', 'WIP', 'Complete', 'WIP', 'Complete', 'WIP', 'Complete', 'Complete'], 'ItemOutcome': ['In', 'WIP', 'Out', 'WIP', 'In', 'WIP', 'In', 'Out'], 'Date': ['01-02-2011', '01-03-2014', '05-02-2010', '01-04-2015', '01-05-2012', '01-02-2013', '01-06-2015', '01-07-2013'] } df = pd.DataFrame(data) # 只保留已完成的项目 completed_df = df[df['ItemStatus'] == 'Complete'] # 按阶段分组,统计In/Out的数量,同时算出每个阶段的总完成数 outcome_counts = completed_df.groupby(['ItemPhase', 'ItemOutcome']).size().unstack(fill_value=0) phase_totals = outcome_counts.sum(axis=1) # 强制阶段按Phase1→Phase2→Phase3的顺序排列,避免乱序 phase_order = ['Phase1', 'Phase2', 'Phase3'] outcome_counts = outcome_counts.reindex(phase_order) phase_totals = phase_totals.reindex(phase_order)
2. 生成和示例一致的上下布局图表
参考你想要的样式,我们做上下两个子图:上方展示各阶段的总完成数(对应示例的Items Status区域),下方用堆叠条形图展示每个阶段的Outcome分布(对应Item Outcomes区域),而且两个图表的x轴完全对齐:
# 先设置个好看的图表风格 plt.style.use('seaborn-v0_8') # 创建画布和两个子图,上下布局,共享x轴,调整上下图的高度比例 fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6), sharex=True, gridspec_kw={'height_ratios': [1, 2]}) # 上方子图:各阶段总完成项目数 x_positions = range(len(phase_order)) ax1.bar(x_positions, phase_totals.values, color='#4a6fe3') ax1.set_ylabel('Completed Items') ax1.set_title('Items Status by Phase') # 给每个柱子加上数值标签,更直观 for idx, total in enumerate(phase_totals.values): ax1.text(idx, total + 0.1, str(total), ha='center', fontsize=10) # 下方子图:各阶段Outcome的堆叠分布 ax2.bar(x_positions, outcome_counts['In'], label='In', color='#2ecc71') ax2.bar(x_positions, outcome_counts['Out'], bottom=outcome_counts['In'], label='Out', color='#e74c3c') ax2.set_xlabel('Item Phase') ax2.set_ylabel('Number of Items') ax2.set_title('Item Outcomes by Phase') ax2.set_xticks(x_positions) ax2.set_xticklabels(phase_order) ax2.legend(loc='upper right') # 自动调整子图间距,避免标题和标签重叠 plt.tight_layout() plt.show()
3. 额外优化:交互式图表(可选)
如果你想要更灵活的交互式效果(比如hover查看具体数值),可以用Plotly来实现,代码也很简单:
import plotly.graph_objects as go from plotly.subplots import make_subplots # 创建上下布局的子图 fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, subplot_titles=['Items Status by Phase', 'Item Outcomes by Phase']) # 上方添加总完成数的柱状图 fig.add_trace(go.Bar(x=phase_order, y=phase_totals.values, name='Completed', marker_color='#4a6fe3'), row=1, col=1) # 下方添加In/Out的堆叠柱状图 fig.add_trace(go.Bar(x=phase_order, y=outcome_counts['In'], name='In', marker_color='#2ecc71'), row=2, col=1) fig.add_trace(go.Bar(x=phase_order, y=outcome_counts['Out'], name='Out', marker_color='#e74c3c'), row=2, col=1) # 调整整体布局 fig.update_layout(barmode='stack', height=600, title_text='Project Phase Progress & Outcomes') fig.update_yaxes(title_text='Completed Items', row=1, col=1) fig.update_yaxes(title_text='Number of Items', row=2, col=1) fig.update_xaxes(title_text='Item Phase', row=2, col=1) # 展示交互式图表 fig.show()
这样生成的图表可以点击图例切换显示,hover时还能看到具体的数值,体验非常棒~
内容的提问来源于stack exchange,提问作者Max Payne
相关产品推荐
相关产品推荐

