77 lines
2.7 KiB
Python
77 lines
2.7 KiB
Python
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.')
|