Matplotlib添加第三个子图报错ValueError: num必须1≤num≤2而非3求解
解决Matplotlib子图布局导致的ValueError问题
嘿,这个问题我一眼就看出来了——你遇到的ValueError: num must be 1 <= num <= 2, not 3完全是因为子图的网格布局设置和分类数量不匹配。
问题根源
你用xox = '21{0}'.format(i)生成子图编号,这个编号的规则是行数+列数+子图索引,也就是说211代表2行1列布局里的第1个子图,212是第2个。这种布局最多只能放2个子图,当你加入第三个分类时,i变成3,生成的213就超出了这个布局的容纳范围,Matplotlib自然就报错了。
快速修复方案
最简单的办法是根据你要展示的分类数量,动态调整子图布局。比如你现在有3个分类,可以改成3行1列的布局(编号用31i),但更优雅的方式是用Matplotlib的plt.subplots直接创建对应数量的子图数组,这样完全不用手动计算子图编号,代码也更清晰。
修改后的完整代码
import matplotlib.pyplot as plt import numpy as np from matplotlib import style # 保留你原有的统计函数(加了ti的初始化,避免潜在的未定义问题) def time_stamp_count(category): tst = [] for i in cc_key_val_num: ti = None # 提前初始化ti,防止后续报错 for k,v in i.items(): if k == 'Time': ti = v[:-2] tst.append({ti:0}) if k == 'LIWC_lib': for x in v: z,q = x if z == category: tst.pop() tst.append({ti:q}) return tst style.use('dark_background') # 注意这里你写了两个相同的focusfuture,可能是笔误,我保留原内容 category_name = ['focusfuture', 'focusfuture', 'focuspresent'] n_categories = len(category_name) # 直接创建对应数量的子图:n行1列,figsize保持你的设置 fig, axes = plt.subplots(n_categories, 1, figsize=(16, 10)) def create_plots(xan): xs = [] ys = [] for i in xan: for k,v in i.items(): xs.append(k) ys.append(v) return xs,ys # 遍历子图和分类名称,一一对应绘制 for ax, step in zip(axes, category_name): xan = time_stamp_count(step) x,y = create_plots(xan) x_freq = 15 x_axis = range(len(x)) my_xticks = np.array(x) # 用面向对象的方式设置刻度,比plt.xticks更适合多子图场景 ax.set_xticks(x_axis[::x_freq]) ax.set_xticklabels(my_xticks[::x_freq]) ax.plot(x_axis,y, label=step, color='#1dcaff') ax.legend() # 每个子图单独加图例,更清晰 # 自动调整子图间距,避免标签重叠 plt.tight_layout() plt.show()
额外优化建议
- 如果想改成横向排列(1行3列),只需要把
plt.subplots(n_categories, 1)改成plt.subplots(1, n_categories)就行。 - 你原代码里的
category_name有两个相同的focusfuture,可能是测试时的笔误,记得后续换成真实的分类名称。 - 用
ax.set_xticks替代plt.xticks是更规范的面向对象写法,在多子图场景下不容易出现混乱。
内容的提问来源于stack exchange,提问作者M4cJunk13
相关产品推荐
相关产品推荐

