90 lines
3.3 KiB
Python
90 lines
3.3 KiB
Python
import matplotlib
|
||
matplotlib.use('Agg')
|
||
import matplotlib.pyplot as plt
|
||
import numpy as np
|
||
|
||
plt.rcParams['font.family'] = 'sans-serif'
|
||
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
|
||
|
||
# Data
|
||
l1 = {2:1887, 3:340, 4:91, 5:41, 6:7, 7:13, 8:4, 9:4, 10:2, 11:2, 12:1, 13:2, 19:1}
|
||
l2 = {2:2249, 3:313, 4:39, 5:10, 6:7, 7:4, 8:1, 9:1, 12:1, 14:1}
|
||
|
||
def group_5plus(d):
|
||
g = {'2次': d.get(2,0), '3次': d.get(3,0), '4次': d.get(4,0),
|
||
'5次': d.get(5,0), '6次+': sum(v for k,v in d.items() if k>=6)}
|
||
return g
|
||
|
||
l1g = group_5plus(l1)
|
||
l2g = group_5plus(l2)
|
||
|
||
cats = list(l1g.keys())
|
||
l1_vals = [l1g[c] for c in cats]
|
||
l2_vals = [l2g[c] for c in cats]
|
||
|
||
fig, axes = plt.subplots(1, 3, figsize=(18, 7))
|
||
|
||
# === Left: Side-by-side bar ===
|
||
x = np.arange(len(cats))
|
||
w = 0.35
|
||
bars1 = axes[0].bar(x - w/2, l1_vals, w, color='#4472C4', label='L1', edgecolor='white')
|
||
bars2 = axes[0].bar(x + w/2, l2_vals, w, color='#ED7D31', label='L2', edgecolor='white')
|
||
|
||
for bar in bars1:
|
||
h = bar.get_height()
|
||
if h > 0:
|
||
axes[0].text(bar.get_x()+bar.get_width()/2, h+max(l1_vals)*0.02, str(int(h)),
|
||
ha='center', fontsize=9, color='#4472C4')
|
||
for bar in bars2:
|
||
h = bar.get_height()
|
||
if h > 0:
|
||
axes[0].text(bar.get_x()+bar.get_width()/2, h+max(l2_vals)*0.02, str(int(h)),
|
||
ha='center', fontsize=9, color='#ED7D31')
|
||
|
||
axes[0].set_xticks(x)
|
||
axes[0].set_xticklabels(cats, fontsize=11)
|
||
axes[0].set_ylabel('重复学习组合数', fontsize=12)
|
||
axes[0].set_title('重复次数分布对比', fontsize=14, fontweight='bold')
|
||
axes[0].legend(fontsize=11)
|
||
axes[0].grid(axis='y', alpha=0.2, linestyle='--')
|
||
axes[0].set_ylim(0, max(max(l1_vals), max(l2_vals))*1.15)
|
||
|
||
# === Middle: L1 pie ===
|
||
l1_pie = [l1g[c] for c in cats]
|
||
l1_total = sum(l1_pie)
|
||
wedges1, _, autotexts1 = axes[1].pie(l1_pie, labels=None,
|
||
colors=['#4472C4','#5B9BD5','#9DC3E6','#BDD7EE','#D6E4F0'],
|
||
autopct='%1.1f%%', startangle=90, textprops={'fontsize': 10})
|
||
axes[1].set_title(f'L1 分布\n(951人, 2,395组合)', fontsize=14, fontweight='bold')
|
||
axes[1].legend(wedges1, [f'{c}: {v} ({v/l1_total*100:.1f}%)' for c,v in zip(cats, l1_pie)],
|
||
loc='lower center', fontsize=9)
|
||
|
||
# === Right: L2 pie ===
|
||
l2_pie = [l2g[c] for c in cats]
|
||
l2_total = sum(l2_pie)
|
||
wedges2, _, autotexts2 = axes[2].pie(l2_pie, labels=None,
|
||
colors=['#ED7D31','#F4B183','#F8CBAD','#FBE5D6','#F2F2F2'],
|
||
autopct='%1.1f%%', startangle=90, textprops={'fontsize': 10})
|
||
axes[2].set_title(f'L2 分布\n(397人, 2,626组合)', fontsize=14, fontweight='bold')
|
||
axes[2].legend(wedges2, [f'{c}: {v} ({v/l2_total*100:.1f}%)' for c,v in zip(cats, l2_pie)],
|
||
loc='lower center', fontsize=9)
|
||
|
||
fig.suptitle('最近3个月(2026.03-05)L1 vs L2 重复学习分布对比',
|
||
fontsize=16, fontweight='bold', y=1.02)
|
||
|
||
# Summary stats
|
||
fig.text(0.5, 0.01,
|
||
f'L1: 活跃7,280人, 重复951人(13.1%), 人均2.5组合, 最高19次 | '
|
||
f'L2: 活跃3,776人, 重复397人(10.5%), 人均6.6组合, 最高14次',
|
||
ha='center', fontsize=10, color='#555')
|
||
|
||
plt.tight_layout(rect=[0, 0.05, 1, 0.95])
|
||
plt.savefig('/root/.openclaw/workspace/output/repeat_l1_l2_3m.png', dpi=150, bbox_inches='tight')
|
||
print('Saved.')
|