matplotlib多行多列子图报错numpy.ndarray无xaxis属性咨询
问题描述
- 尝试创建包含多个子图的可视化图表时,触发以下报错:
AttributeError: 'numpy.ndarray' object has no attribute 'xaxis'
- 触发报错的代码如下:
plt.figure() n_cols = 6 n_rows = int(len(df.foo.unique()) / n_cols) # 计算结果为4 fn, axis = plt.subplots(nrows=n_rows, ncols=n_cols, figsize=(30, 25)) for i in range(len(df.foo.unique())): sb.scatterplot(x='var1', y='var2', hue='foo', data=df[df.foo == i], ax=axis[i])
代码说明:字段foo取值范围为0-23,共24个唯一值。
- 当把子图参数修改为1行12列时,代码可正常运行无报错,对应代码如下:
plt.figure() fn, axis = plt.subplots(nrows=1, ncols=12, figsize=(30, 25)) for i in range(len(df.foo.unique())): sb.scatterplot(x='var1', y='var2', hue='foo', data=df[df.foo == i], ax=axis[i])
- 报错完整堆栈信息:
File c:\Users\user\anaconda3\envs\ml\lib\site-packages\seaborn\_decorators.py:46, in _deprecate_positional_args.<locals>.inner_f(*args, **kwargs) 36 warnings.warn( 37 "Pass the following variable{} as {}keyword arg{}: {}. " 38 "From version 0.12, the only valid positional argument " (...) 43 FutureWarning 44 ) 45 kwargs.update({k: arg for k, arg in zip(sig.parameters, args)}) ---> 46 return f(**kwargs) File c:\Users\user\anaconda3\envs\ml\lib\site-packages\seaborn\relational.py:825, in scatterplot(x, y, hue, style, size, data, palette, hue_order, hue_norm, sizes, size_order, size_norm, markers, style_order, x_bins, y_bins, units, estimator, ci, n_boot, alpha, x_jitter, y_jitter, legend, ax, **kwargs) 822 if not p.has_xy_data: 823 return ax ---> 825 p._attach(ax) 827 p.plot(ax, kwargs) 829 return ax File c:\Users\user\anaconda3\envs\ml\lib\site-packages\seaborn\_core.py:1134, in VectorPlotter._attach(self, obj, allowed_types, log_scale) ... -> 1134 axis = getattr(ax, f"{var}axis") 1135 seed_data = self.plot_data[var] 1136 if var_type == "categorical": AttributeError: 'numpy.ndarray' object has no attribute 'xaxis'
报错原因
核心原因是plt.subplots()返回的坐标轴数组维度,会随子图的行列设置变化:
- 当设置
nrows=1且ncols>1(或者ncols=1且nrows>1)时,返回的axis是一维numpy数组,直接用axis[i]索引就能拿到单个子图的坐标轴对象,所以1行12列的代码可以正常运行。 - 当同时设置
nrows>1且ncols>1时,返回的axis是二维numpy数组,形状为(n_rows, n_cols)。这时候用axis[i]索引,拿到的不是单个坐标轴对象,而是第i行对应的整行子图数组(类型仍然是numpy.ndarray),把数组传给scatterplot的ax参数,seaborn尝试访问数组的xaxis属性自然会触发报错。
修复方法
两种常用改法任选其一即可:
- 把二维坐标轴数组展平为一维,再按索引取值:
plt.figure() n_cols = 6 n_rows = int(len(df.foo.unique()) / n_cols) # 4 fn, axis = plt.subplots(nrows=n_rows, ncols=n_cols, figsize=(30, 25)) # 展平二维数组为一维 axis = axis.flatten() for i in range(len(df.foo.unique())): sb.scatterplot(x='var1', y='var2', hue='foo', data=df[df.foo == i], ax=axis[i])
- 索引时传入行列坐标定位单个子图:
plt.figure() n_cols = 6 n_rows = int(len(df.foo.unique()) / n_cols) # 4 fn, axis = plt.subplots(nrows=n_rows, ncols=n_cols, figsize=(30, 25)) for i in range(len(df.foo.unique())): # 计算当前索引对应的行号、列号 row_idx = i // n_cols col_idx = i % n_cols sb.scatterplot(x='var1', y='var2', hue='foo', data=df[df.foo == i], ax=axis[row_idx, col_idx])
内容的提问来源于stack exchange,提问作者OK 400
相关产品推荐
相关产品推荐

