pythonvalueerrorerrorbar

Why is there a ValueError if all input columns are the same size (22,1) for errorbar matplotlib plot?


I am trying to include error bars on a scatter plot based off a column from a dataframe that contains standard deviations. The x values are subjects from a study and the y values are associated ITA values. I'm getting a value error when I try to run the code, however, when I check the shapes of each necessary column I find that they are the same. Unsure what the error is suggesting. Any help would be appreciated! My code/output is listed below:

Input:

x1=df_pre_means_ITA[[('subj', '')]]
y1=df_pre_means_ITA[[('subsite_1_ITA', 'mean_values')]]
yerr1=df_pre_std_ITA[[('subsite_1_ITA', 'std_values')]]
print(x1.shape,y1.shape,yerr1.shape)

Output:

(22, 1) (22, 1) (22, 1)

Input:

plt.figure("Subsite 1 Mean ITA Values by Subject")
plt.errorbar(x=x1, y=y1, yerr=yerr1, fmt='o',linewidth=2,capsize=6)
plt.show()

Output:

ValueError                                Traceback (most recent call last)
Cell In[293], line 2
      1 plt.figure("Subsite 1 Mean ITA Values by Subject")
----> 2 plt.errorbar(x=x1, y=y1, yerr=yerr1, fmt='o',linewidth=2,capsize=6)
      3 # ax.errorbar(x=x1, y=y1, yerr=yerr1, fmt='o',linewidth=2,capsize=6)
      4 plt.show()

File ~\AppData\Local\anaconda3\Lib\site-packages\matplotlib\pyplot.py:2564, in errorbar(x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, data, **kwargs)
   2558 @_copy_docstring_and_deprecators(Axes.errorbar)
   2559 def errorbar(
   2560         x, y, yerr=None, xerr=None, fmt='', ecolor=None,
   2561         elinewidth=None, capsize=None, barsabove=False, lolims=False,
   2562         uplims=False, xlolims=False, xuplims=False, errorevery=1,
   2563         capthick=None, *, data=None, **kwargs):
-> 2564     return gca().errorbar(
   2565         x, y, yerr=yerr, xerr=xerr, fmt=fmt, ecolor=ecolor,
   2566         elinewidth=elinewidth, capsize=capsize, barsabove=barsabove,
   2567         lolims=lolims, uplims=uplims, xlolims=xlolims,
   2568         xuplims=xuplims, errorevery=errorevery, capthick=capthick,
   2569         **({"data": data} if data is not None else {}), **kwargs)

File ~\AppData\Local\anaconda3\Lib\site-packages\matplotlib\__init__.py:1442, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1439 @functools.wraps(func)
   1440 def inner(ax, *args, data=None, **kwargs):
   1441     if data is None:
-> 1442         return func(ax, *map(sanitize_sequence, args), **kwargs)
   1444     bound = new_sig.bind(ax, *args, **kwargs)
   1445     auto_label = (bound.arguments.get(label_namer)
   1446                   or bound.kwargs.get(label_namer))

File ~\AppData\Local\anaconda3\Lib\site-packages\matplotlib\axes\_axes.py:3635, in Axes.errorbar(self, x, y, yerr, xerr, fmt, ecolor, elinewidth, capsize, barsabove, lolims, uplims, xlolims, xuplims, errorevery, capthick, **kwargs)
   3633     np.broadcast_to(err, (2, len(dep)))
   3634 except ValueError:
-> 3635     raise ValueError(
   3636         f"'{dep_axis}err' (shape: {np.shape(err)}) must be a "
   3637         f"scalar or a 1D or (2, n) array-like whose shape matches "
   3638         f"'{dep_axis}' (shape: {np.shape(dep)})") from None
   3639 res = np.zeros(err.shape, dtype=bool)  # Default in case of nan
   3640 if np.any(np.less(err, -err, out=res, where=(err == err))):
   3641     # like err<0, but also works for timedelta and nan.

ValueError: 'yerr' (shape: (22, 1)) must be a scalar or a 1D or (2, n) array-like whose shape matches 'y' (shape: (22, 1))

I have tried checking the shapes of each column and found that they are the same (22,1) shaped array. The value error presented suggests that it thinks I'm inputting different sized arrays. Not sure how to proceed.


Solution

  • You seem to have 3 2-dimentional arrays with trivial second dimention, ex. [[1, 2, 3]] (here shape is (3, 1)). What the error text says - that the function demands 1d array, ex. [1, 2, 3] (shape (3, )).

    You can get yerr1 as yerr1 = df_pre_std_ITA[('subsite_1_ITA', 'std_values')] to get 1d shaped vectors (1 pair of square brackets, not 2).