import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import matplotlib.ticker as mticker import numpy as np # Data months = ['2025-03','2025-04','2025-05','2025-06','2025-07','2025-08', '2025-09','2025-10','2025-11','2025-12', '2026-01','2026-02','2026-03','2026-04','2026-05'] monthly = [19,6,8,28,30,45,145,81,126,125,107,140,391,692,519] cumulative = np.cumsum(monthly) # Style plt.rcParams['font.family'] = 'sans-serif' # Try to use a Chinese font for f in ['WenQuanYi Micro Hei', 'Noto Sans CJK SC', 'SimHei', 'DejaVu Sans']: try: plt.rcParams['font.sans-serif'] = [f] break except: continue plt.rcParams['axes.unicode_minus'] = False fig, ax1 = plt.subplots(figsize=(14, 7)) x = range(len(months)) # Bar chart - monthly bars = ax1.bar(x, monthly, width=0.6, color='#5B9BD5', alpha=0.85, label='当月重复学习用户数', zorder=2) ax1.set_ylabel('当月重复学习用户数', fontsize=13, color='#5B9BD5') ax1.tick_params(axis='y', labelcolor='#5B9BD5') ax1.set_ylim(0, max(monthly) * 1.3) # Data labels on bars for i, (xi, v) in enumerate(zip(x, monthly)): if v > 0: ax1.text(xi, v + max(monthly)*0.02, str(v), ha='center', va='bottom', fontsize=9, color='#5B9BD5') # Line chart - cumulative ax2 = ax1.twinx() line = ax2.plot(x, cumulative, 'o-', color='#ED7D31', linewidth=2.5, markersize=6, label='累计重复学习用户数', zorder=3) ax2.set_ylabel('累计重复学习用户数', fontsize=13, color='#ED7D31') ax2.tick_params(axis='y', labelcolor='#ED7D31') ax2.set_ylim(0, cumulative[-1] * 1.2) # Data labels on cumulative line for i, (xi, v) in enumerate(zip(x, cumulative)): ax2.text(xi, v + cumulative[-1]*0.015, str(v), ha='center', va='bottom', fontsize=8, color='#ED7D31') # X-axis ax1.set_xticks(x) ax1.set_xticklabels(months, rotation=45, ha='right', fontsize=10) ax1.set_xlabel('月份', fontsize=13) # Title ax1.set_title('重复学习用户月度趋势(同一用户对同一课时完成≥2次)', fontsize=16, fontweight='bold', pad=20) # Grid ax1.grid(axis='y', alpha=0.3, linestyle='--') ax1.set_axisbelow(True) # Legend lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left', fontsize=11) # Annotation ax1.annotate('3月核心版本上线后\n重复学习用户快速增长', xy=(12, 391), xytext=(9, 550), arrowprops=dict(arrowstyle='->', color='#333', lw=1.5), fontsize=10, color='#333', bbox=dict(boxstyle='round,pad=0.3', facecolor='#FFF2CC', alpha=0.8)) plt.tight_layout() plt.savefig('/root/.openclaw/workspace/output/repeat_learn_trend.png', dpi=150, bbox_inches='tight') print('Chart saved.')