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

基于Python和Pandas优化学生课程表可视化的方案咨询

课程表可视化:重叠课程堆叠显示问题

问题背景与需求

我用Pandas DataFrame存储课程表数据,想要将其可视化成重叠课程堆叠显示的样式。目前基于ChatGPT 3.5生成并修改的Matplotlib条形图代码,仅能勉强处理周一上午的部分重叠,完全遗漏周一下午的重叠情况,无法达到理想的堆叠效果。

我设想了两种修复方案,但都觉得过于繁琐:

  • 从周五(图表底部)开始计算每日重叠课程数,设置Y轴位置后依次处理其他日期;
  • 忽略重叠判断,按每日课程数量统一偏移所有课程条,该方案虽会导致非重叠课程无法对齐,但可接受。

希望找到更简便的实现方式,比如适配的图表类型、第三方库或编码技巧,同时满足以下补充需求:

  • 重叠课程不常见,尽量保持非重叠课程水平对齐;
  • 支持2门及以上课程同时重叠的场景。

现有代码

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

# Sample DataFrame
data = {
    'CCode': ['BABM701','BABM701', 'DCFE700', 'MG6051', 'DCFE700', 'MG6051'],
    'SG': ['All','All',  'All', 'A', 'All','A'],
    'StartTime': ['09:00:00','13:00:00', '09:00:00','09:00:00', '13:00:00','10:00:00'],
    'EndTime': ['12:00:00', '14:30:00','14:30:00','12:00:00', '14:30:00','12:00:00'],
    'Day': ['Mon', 'Mon','Mon', 'Thu', 'Thu','Fri'],
    'Room': ['X310','X310', 'K312','K225', 'K312','K225']
}

df = pd.DataFrame(data)

# Convert the 'StartTime' and 'EndTime' to datetime format
df['StartTime'] = pd.to_datetime(df['StartTime'], format='%H:%M:%S').dt.time
df['EndTime'] = pd.to_datetime(df['EndTime'], format='%H:%M:%S').dt.time

# Get unique CCode values and assign colors automatically
unique_ccodes = df['CCode'].unique()
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_ccodes)))  # Using tab20 colormap
color_map = {ccode: colors[i] for i, ccode in enumerate(unique_ccodes)}

# Create the plot
plt.figure(figsize=(12, 6))

# Set the y-position for the bars
y_positions = {'Mon': 4, 'Tue': 3, 'Wed': 2, 'Thu': 1, 'Fri': 0}

# Find the earliest start time and latest end time
earliest_start = min(9, df['StartTime'].apply(lambda x: x.hour + x.minute/60).min())
latest_end = max(17, df['EndTime'].apply(lambda x: x.hour + x.minute/60).max())

# Adjust y-positions based on overlaps
for day in df['Day'].unique():
    day_df = df[df['Day'] == day].sort_values(by='StartTime')
    overlap_count = np.zeros(len(day_df))
    
    for i in range(len(day_df)):
        for j in range(i + 1, len(day_df)):
            if day_df.iloc[i]['EndTime'] > day_df.iloc[j]['StartTime'] and day_df.iloc[i]['StartTime'] < day_df.iloc[j]['EndTime']:
                overlap_count[j] += 1
                
    day_df['Overlap'] = overlap_count
    
    # Plot bars for the day with adjusted height for overlapping courses
    for idx, row in day_df.iterrows():
        duration = (pd.Timestamp.combine(pd.Timestamp.today(), row['EndTime']) - pd.Timestamp.combine(pd.Timestamp.today(), row['StartTime'])).seconds/3600
        x_position = row['StartTime'].hour + row['StartTime'].minute/60
        y_position = y_positions[day] - row['Overlap'] * 0.5  # Adjusting y position based on overlap
        plt.barh(y=y_position, width=duration, left=x_position, color=color_map[row['CCode']], alpha=0.7, edgecolor='grey', label=row['CCode'])
        
        # Annotate the bar with CCode and SG
        label = f"{row['CCode']} {row['SG']}"
        plt.text(x=x_position + duration/2, y=y_position, s=label, color='black', va='center', ha='center')

# Customize the plot
plt.xlabel('Time')
plt.ylabel('Day')
plt.title('Course Schedule')
plt.xlim(earliest_start, latest_end)
plt.xticks(np.arange(earliest_start, latest_end + 1, 1))
plt.yticks([0, 1, 2, 3, 4], ['Fri', 'Thu', 'Wed', 'Tue', 'Mon'])
plt.grid(axis='x', linestyle='--', alpha=0.7)
plt.legend(loc='upper right')
plt.tight_layout()

# Show the plot
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:12:48