matplotlib throws error with figure.canvas.draw() and figure.savefig(): "ValueError: Expected 2-dimensional array, got 1"

matplotlib throws error with figure.canvas.draw() and figure.savefig(): "ValueError: Expected 2-dimensional array, got 1"

我想绘制一个图形,我需要在其中比较图例和图形高度。 所需的输出如下所示:

以前它很管用,现在我无法绘制存储在变量 fig 中的图形。

为此,有必要在实际绘图之前绘制图形 canvas,因为这样才能获得真正的最终图形扩展。

fig.canvas.draw()

# Get the extensions/dimensions of the current axis and legend
ax_height = ax.get_window_extent().height
ax_width = ax.get_window_extent().width
leg_height = legend.get_window_extent().height
leg_width = legend.get_window_extent().width

至少在以前,行 fig.canvas.draw() 工作完美,但这次抛出以下错误(包括整个回溯):

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/andylu/Dokumente/Allgemeines_material/Sonstiges/Programming/Python/Scripts/General/Plotting/auxiliary_plotting_functions.py", line 1293, in compare_legend_figure_height
    fig.canvas.draw()
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 407, in draw
    self.figure.draw(self.renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/figure.py", line 1863, in draw
    mimage._draw_list_compositing_images(
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py", line 411, in wrapper
    return func(*inner_args, **inner_kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/axes/_base.py", line 2748, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/collections.py", line 931, in draw
    Collection.draw(self, renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/collections.py", line 406, in draw
    renderer.draw_path_collection(
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 172, in draw_path_collection
    return self._renderer.draw_path_collection(
ValueError: Expected 2-dimensional array, got 1

在调试控制台中,可以得到额外的inside into figure变量,但并没有帮助我进一步解决问题:

fig
<Figure size 1000x750 with 6 Axes>
special variables
function variables
artists:[]
axes:[<AxesSubplot:title={...19-pos4'}>, <AxesSubplot:title={...18-pos1'}>, <AxesSubplot:title={...18-pos1'}>, <AxesSubplot:title={...19-pos4'}>, <AxesSubplot:>, <AxesSubplot:>]
bbox:<matplotlib.transforms.TransformedBbox object at 0x7fc780543310>
bbox_inches:Bbox([[0.0, 0.0], [10.0, 7.5]])
callbacks:<matplotlib.cbook.CallbackRegistry object at 0x7fc7795fa3a0>
canvas:<matplotlib.backends.backend_agg.FigureCanvasAgg object at 0x7fc7811c1850>
clipbox:None
dpi:100.0
dpi_scale_trans:<matplotlib.transforms.Affine2D object at 0x7fc780543640>
eventson:False

figure:None
frameon:True
images:[]
legends:[]
lines:[]
mouseover:False
number:1
patch:<matplotlib.patches.Rectangle object at 0x7fc780554eb0>
patches:[]
stale:False
sticky_edges:_XYPair(x=[], y=[])
subplotpars:<matplotlib.figure.SubplotParams object at 0x7fc7795fa040>
suppressComposite:None
texts:[]
transFigure:<matplotlib.transforms.BboxTransformTo object at 0x7fc7805433a0>
zorder:0
_add_axes_internal:<bound method Figure._add_axes_internal of <Figure size 1000x750 with 6 Axes>>

_agg_filter:None
_align_xlabel_grp:<matplotlib.cbook.Grouper object at 0x7fc7795fac10>
_align_ylabel_grp:<matplotlib.cbook.Grouper object at 0x7fc7795faf10>
_alpha:None
_animated:False
_axobservers:<matplotlib.cbook.CallbackRegistry object at 0x7fc7811c1b50>
_axstack:<matplotlib.figure._AxesStack object at 0x7fc7795fae20>
_cachedRenderer:<matplotlib.backends.backend_agg.RendererAgg object at 0x7fc780d235e0>
_clipon:True
_clippath:None
_constrained:False
_constrained_layout_pads:{'h_pad': 0.04167, 'hspace': 0.02, 'w_pad': 0.04167, 'wspace': 0.02}
_contains:None
_default_contains:<bound method Artist._default_contains of <Figure size 1000x750 with 6 Axes>>
_dpi:100.0
_gci:<bound method Figure._gci of <Figure size 1000x750 with 6 Axes>>
_label:''
_layoutbox:None
_make_key:<bound method Figure._make_key of <Figure size 1000x750 with 6 Axes>>
_mouseover:False
_normalize_grid_string:<function Figure._normalize_grid_string at 0x7fc7d437c3a0>
_oid:0
_path_effects:[]
_picker:None
_process_projection_requirements:<bound method Figure._process_projection_requirements of <Figure size 1000x750 with 6 Axes>>
_propobservers:{}
_rasterized:None
_remove_method:None
_repr_html_:<bound method Figure._repr_html_ of <Figure size 1000x750 with 6 Axes>>
_set_artist_props:<bound method Figure._set_artist_props of <Figure size 1000x750 with 6 Axes>>
_set_dpi:<bound method Figure._set_dpi of <Figure size 1000x750 with 6 Axes>>
_set_gc_clip:<bound method Artist._set_gc_clip of <Figure size 1000x750 with 6 Axes>>
...

满怀希望,我试着像这样简单地避免这个错误:

# NOTE on scope of drawing the figure canvas:
# Crucial in order to get real legend extent afterwards
try:
    fig.canvas.draw()
except Exception as e:
    tools.except_print(f"The exception thrown opon executing fig.canvas.draw was:\n{e}\nExecute the rest of this function nevertheless.")

然而,通过figure.savefig()保存图形时出现了类似的错误,所以我无法避免解决这个问题:

fig.savefig(filename,
            dpi=dpi,
            bbox_inches=bbox_inches,
            transparent=transparent)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/figure.py", line 2311, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 2210, in print_figure
    result = print_method(
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 1639, in wrapper
    return func(*args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 509, in print_png
    FigureCanvasAgg.draw(self)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 407, in draw
    self.figure.draw(self.renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/figure.py", line 1863, in draw
    mimage._draw_list_compositing_images(
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py", line 411, in wrapper
    return func(*inner_args, **inner_kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/axes/_base.py", line 2748, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py", line 132, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/collections.py", line 931, in draw
    Collection.draw(self, renderer)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/collections.py", line 406, in draw
    renderer.draw_path_collection(
  File "/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 172, in draw_path_collection
    return self._renderer.draw_path_collection(
ValueError: Expected 2-dimensional array, got 1

我在这个上下文中使用的最内层的绘图函数是:

def plot_point_estimator_with_CI(
    df_plot_list=None,
    colname=None,
    estimator="mean",
    ci_color=[1, 0, 0, 0.15],
    CI=0.95,
    hor_line=None,
    strftime_str=None,
    outer_index=None,
    all_outer_indexes_subplot=False,
    groupby_freq=None,
    ax_title_pos=None,
    savepath=None,
    filtered_gps=None):

# Check for existence of the savepath
if savepath is not None and not os.path.exists(savepath):
    os.makedirs(savepath)

# * Create a dummy date for later combination with pure time-values (i.e. HH:MM:SS)
# NOTE on scope: this is needed for being able to be plotted on a matplotlib.ax since datetime.time()-arrays will throw errors
# NOTE on implementation: use an extra-weird date in order to make clear that this is certainly not a real date
dummy_date = datetime.date(1000, 10, 10)

if not all_outer_indexes_subplot:
    loop2_list = filtered_gps
else:
    loop2_list = outer_index

## ** SUBPLOTS
"""Prepare the figure dimensions:
# NOTE: the figure size should be decided according to the dimensions of the grid
# Syntax from the documentation under: https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.figure.html
# (float, float), optional, default: None
# width, height in inches. If not provided, defaults to rcParams["figure.figsize"] = [6.4, 4.8]
# -> the relation is 4:3, which will be maintained throughout this
# CAUTION: even when cols=rows, the figure needs to be wider than high."""
if cols >= rows:
    width = 10
    height = width * (3 / 4)
else:  # cols < rows:
    height = 10
    width = height * (3 / 4)

# * Instantiate figure
fig, axs = plt.subplots(rows, cols, figsize=(width, height))

# * Turn off possible extant subplot axes
dim_subplot = rows * cols
if len(loop2_list) < dim_subplot and len(loop2_list) > 1:
    subplot_ax_overshoot = True
    # Could happen when uneven number of subplots, such as "5", is passed, and the rectangular grid
    # has extant subplot axis, e.g. in the case of a 2*3 = 6 grid
    for i in range(len(loop2_list), dim_subplot):
        axs.ravel()[i].axis('off')
else:
    subplot_ax_overshoot = False

# Adapt the fontsize of the axis title strings according to the column number of the subplot
if cols < 3:  # should be the "maximum max_cols_per_row"
    ax_title_fontsize = 9
    if not particular_ax_label_fontsize:
        particular_ax_label_fontsize = 9
    legend_font_size = 8.25
    # NOTE on linewidths: the more columns/subplot graphic number, the finer the lines should be
    if cols < 2:
        linewidth = None  # standard seems ok
    else:
        linewidth = 1.25
else:
    ax_title_fontsize = 7
    if not particular_ax_label_fontsize:
        particular_ax_label_fontsize = 8
    linewidth = 1
    legend_font_size = 7

# NOTE: this is paramount in order to display the CI-band in the end as a part of the legend, even though the last subplot didn't contain it
add_handles_labels = None

# * Loop 2 - Create the output graphics
for i, elem in enumerate(loop2_list):
    if groupby_freq is not None:
        if groupby_freq.lower() == "y":
            # Extract the grouped-by unit of the current pd.Timestamp
            coord_kw = int(elem[0].strftime(
                strftime_str))  # could be year, month, ...
            # Assign a time unit name to the title string of the current sub-plot axis
            current_ax_title = coord_kw
        elif groupby_freq.lower() == "m":
            # Extract the grouped-by unit of the current pd.Timestamp
            coord_kw = int(elem[0].strftime(
                strftime_str))  # could be year, month, ...
            # Assign a time unit name to the title string of the current sub-plot axis
            current_ax_title = calendar.month_name[coord_kw]
        else:
            string = """\nERROR: if the time-groupingby-frequency is neither "Y" nor "M",
it hasn't been implemented yet. Won't execute the plotting code (for this iteration).\nCurrent groupby_freq: '{}'""".format(
                    groupby_freq)
                tools.except_print(string)
                break
        elif all_outer_indexes_subplot:
            # The current outer index / directory / location name of the given meteo or gas measuring data
            current_ax_title = elem
            coord_kw = elem

    # Define a temporary variable for the current sub-set dataframe
    sub_df = df_plot_list[i]
    if type(sub_df) == pd.DataFrame:
        sub_df.dropna(axis=1, how="all", inplace=True)

    # Assign the row and column to the current month accordingly - from dictionary
    # NOTE: it should be ordered from January upper-left to December bottom-right
    row, col = row_col_coords[coord_kw]
    # Pass the info to the axis-dummy variable for the following plotting commands
    if len(loop2_list) > 1:
        # Discerning is paramount for avoiding "IndexError: too many indices for array"
        if rows > 1 and cols > 1:
            ax = axs[row, col]
        elif rows > 1:  # cols = 1
            ax = axs[row]
        else:  # rows = 1
            ax = axs[col]
    # Case of single plot: rows = cols = 1
    else:
        # Avoid error: "is not subscriptable" when it's not a real subplot but only 1 plot
        ax = axs

    # * Check for datetime.time - format of index (overlay of days or similar)
    if isinstance(sub_df.index[0], datetime.time):
        # NOTE on implementation:
        # - Replaced df_dummy.index.time with [datetime.datetime.combine(dummy_date, t) for t in df_dummy.index.time] since datetime.time(22, 35)-objects can't be processed well with ax.plot()
        # Docs: 
        sub_df.index = [
            datetime.datetime.combine(dummy_date, t) for t in sub_df.index
        ]
        update_ticks_to_full_fledged_datetime = True
    else:
        update_ticks_to_full_fledged_datetime = False

    # * Create plot on the designated axis based on the current sub-df
    if type(sub_df) == pd.DataFrame:  # contains CI-bands
        # Caution: Colnames are uppercase conventionally
        # NOTE: optionally another kwarg could be added: label=str_man.uppercase(estimator)
        line1, = ax.plot(
            sub_df.loc[:, str_man.uppercase(estimator)],
            label=str_man.uppercase(estimator),
            linewidth=linewidth)  # matplotlib.lines.Line2D object
        # Confidence interval of fit (higher resolution due to generated fit-vals with higher density)
        # NOTE: the comma "," needs to be left out, otherwise: "TypeError: cannot unpack non-iterable PolyCollection object"
        line2_label = "{}% CI".format(str(round(CI * 100)))
        line2 = ax.fill_between(sub_df.index,
                                sub_df.loc[:, "Lower_bound"],
                                sub_df.loc[:, "Upper_bound"],
                                color=ci_color,
                                edgecolor="",
                                label=line2_label)
        if not hor_line or i == len(loop2_list) - 1:
            # NOTE on handles: could also be without "handles=.."
            legend = aux_plot.set_legend_with_sorted_labels(
                fig=fig,
                ax=ax,
                handles=[line1, line2],
                return_legend_n_its_position=True)[0]
            if i == len(loop2_list) - 1:
                # Set to None, as the CI-band (line2) has just been plotted in the last subplot axis
                add_handles_labels = None
        else:
            # NOTE: this is paramount in order to display the CI-band in the end as a part of the legend, even though the last subplot didn't contain it
            if not add_handles_labels:
                add_handles_labels = [line2, line2_label]

    # Contains only the aggregated values of the statistical summary estimator, i.e. type(df) == pd.Series
    else:
        # pd.Series doesn't need any other kwargs to be passed
        line1, = ax.plot(sub_df,
                         label=str_man.uppercase(estimator),
                         linewidth=linewidth)
        if not hor_line or i == len(loop2_list) - 1:
            # NOTE on handles: could also be without "handles=.."
            legend = aux_plot.set_legend_with_sorted_labels(
                fig=fig,
                ax=ax,
                handles=[line1],
                return_legend_n_its_position=True)[0]

    # * SET X-TICKS and -LABELS
    # Create a grid for the times on the x-axis
    times_grid, time_ax_vals, ax_tick_labels, sub_ordinated_unit = dt_man.time_range_grid_and_vals(
        step=step, cols=cols)
    # Delete superfluous variables
    del time_ax_vals

    # * Set the ticks and their associated labels
    if update_ticks_to_full_fledged_datetime:
        # NOTE on implementation: need to adapted with the dummy-date to the current axis
        # -> The date doesn't matter since the ticks will be labeled separately with the "HH:MM:SS" - strings (pure times)
        ax.set_xticks(
            [datetime.datetime.combine(dummy_date, t) for t in times_grid])
    else:
        ax.set_xticks(times_grid)
    # Tick labels remain untouched by the ticks-setting above
    ax.set_xticklabels(ax_tick_labels,
                       fontsize=particular_ax_label_fontsize)

    # * SET Y-TICKS and -LABELS
    y_tick_labels = [str(yt) for yt in list(ax.get_yticks())]
    if decimal_formatter:
        y_tick_labels = [
            decimal_formatter % Decimal(float(t)) for t in y_tick_labels
        ]
    y_tick_labels = tools.round_long_floats_with_many_zeros(
        number_list=y_tick_labels,
        decimal_sep=".",
        undesired_char="0",
        limit_consec_undesired_chars=1)
    ax.set_yticklabels(y_tick_labels,
                       fontsize=particular_ax_label_fontsize)
    ax.grid(which='both', alpha=1)

    # Inserts horizontal line into plot adapted by its value in comparison to the data's values
    # NOTE: only the last element, which is true in case of a subplot or a single plot
    if hor_line is not None:
        remove_legend_from_current_axis = i != len(loop2_list) - 1
        # Loop over all horizontal lines provided
        for hor in hor_line:
            if hor[0].lower() in colname.lower(
            ):  # hor[0] contains the variable name (or vice versa)
                # hor[1] contains tuples (triples)
                for info, val, linestyle in hor[1]:
                    leg_label = str_man.uppercase(info)

                    # Caution 1: In order to obtain pd.Datetime-vals from matplotlib's ax.get_xlim() -> conversion necessary
                    # Caution 2: Set vertical=False since horizontal lines are desired
                    # NOTE on previous implementation of other_ax_vals:
                    # i) time_ax_vals
                    # ii) [datetime.datetime.combine(dummy_date, t) for t in time_ax_vals]
                    ax, legend = aux_plot.add_hor_vert_line_n_legend(
                        ax=ax,
                        compare_ax_vals=ax.get_ylim(),
                        add_handles_labels=add_handles_labels,
                        other_ax_vals=ax.get_xlim(),
                        val=val,
                        alpha=1,
                        linewidth=linewidth,
                        leg_label=leg_label,
                        vertical=False,
                        linestyle=linestyle,
                        remove_legend_from_current_axis=
                        remove_legend_from_current_axis)[:2]

    # * X-axis label
    # NOTE: otherwise, it appears always the string "time"
    ax.set_xlabel("")

    # * Title of current axis
    # Set title with the calendar month above every subplot
    # [x_coord, y_coord] -> slightly above the top and centered
    ax.set_title(current_ax_title,
                 position=ax_title_pos,
                 fontsize=ax_title_fontsize)

# * AFTER 2nd LOOP
# 0.0) Assign global axis label shifts
global_X_ax_label_shift = global_X_ax_label_shift_dict[rows]
global_Y_ax_label_shift = global_Y_ax_label_shift_dict[rows]

# 0.1) Create final and global legend object
if hor_line is not None and dim_subplot > 1:
    # Obtain legend handles and labels from passed axis object
    handles, labels = ax.get_legend_handles_labels()
    # NOTE: sometimes it is necessary to pass former handles and labels from an already plotted axis
    # TIPP: the problem is that when the current axis is accessed for retrieving the handles and labels, these added
    # handles and labels won't be in there since it was nothing plotted in the current axis, but in a former one
    if add_handles_labels:
        # Extract the additional handles and labels from another/former axis
        add_handles, add_labels = add_handles_labels
        # Add these accordingly to the current axis' handles..
        if type(add_handles) != list:
            handles += [add_handles]
        else:
            handles += add_handles
        # .. and labels
        if type(add_labels) != list:
            labels += [add_labels]
        else:
            labels += add_labels

    # CAUTION: Prevent the legend's appearance in the last selected axis of the subplot
    ax.get_legend().remove()

    legend_font_size = 8.25
    # NOTE on the nomenclature of this legend:
    # - bbox_to_anchor = (x, y), alternatively, if a size needs to be determined: (x, y, width, height)
    # - loc == 9 -> upper center, (0, 0) seems to stand for the lower/upper left corner of the legend box
    # - ncol : The number of columns that the legend has. Default is 1.
    # - mode: If mode is set to "expand" the legend will be horizontally expanded to fill the axes area
    # (or bbox_to_anchor if defines the legend's size, which is the case if a 4-tuple was passed to bbox_to_anchor like (x, y, width, height))
    if not subplot_ax_overshoot:
        aux_plot.set_legend_with_sorted_labels(fig=fig,
                                               handles=handles,
                                               labels=labels,
                                               loc="lower center",
                                               ncol=5,
                                               fontsize=legend_font_size)

        global_X_ax_label_shift += 0.01  # shift higher to make room for the footnote-legend
    # * OTHERWISE, use the last free axis to plot the legend
    else:
        legend_ax = axs[rows - 1, cols - 1]
        # Set sorted legend on specific axis
        aux_plot.set_legend_with_sorted_labels(ax=legend_ax,
                                               handles=handles,
                                               labels=labels,
                                               loc="upper left",
                                               ncol=1,
                                               fontsize=legend_font_size)

# 0.2) Set global X- and Y-axis labels
xaxstr = "Time ({})".format(sub_ordinated_unit)
if yaxstr is None:
    yaxstr = str_man.uppercase(estimator)
if len(df_plot_list) == 1:
    ax.set_xlabel(xaxstr, fontsize=ax_label_font_size)
    ax.set_ylabel(yaxstr, fontsize=ax_label_font_size)
else:

    fig.text(0.5,
             global_X_ax_label_shift,
             xaxstr,
             ha='center',
             rotation='horizontal',
             fontsize=ax_label_font_size)  # general x-axis label
    fig.text(global_Y_ax_label_shift,
             0.5,
             yaxstr,
             va='center',
             rotation='vertical',
             fontsize=ax_label_font_size)  # general y-axis label

# 1) Generate a unique title string
# ...

# 2) Set title
if len(df_plot_list) == 1:
    # NOTE: overlapping title strings with the standard .set_title()-function can be fought via the y-kwarg
    ax.set_title(titlestr,
                 y=1.0 + add_to_ycoord / 2,
                 fontsize=title_font_size,
                 weight="bold")
    fig.tight_layout()
else:
    # Now, alter the y-coord of the superior title as a function of the lines the suptitlestring comprises
    y_coord_suptitle = y_coord_suptitle_dict[rows]
    y_coord_suptitle += add_to_ycoord

    # Finally, set the suptitle
    plt.suptitle(titlestr,
                 x=0.5,
                 y=y_coord_suptitle,
                 fontsize=title_font_size,
                 weight="bold")
    # NOTE: Tight layout often produces nice results, but requires the title to be spaced accordingly
    fig.tight_layout()

    if global_Y_ax_label_shift:
        # ...

        fig.subplots_adjust(top=y_coord_suptitle + sub_top_shift -
                            add_to_ycoord,
                            bottom=global_X_ax_label_shift + 0.04,
                            left=global_Y_ax_label_shift + add_left_shift)
    else:
        fig.subplots_adjust(top=y_coord_suptitle + sub_top_shift -
                            add_to_ycoord,
                            bottom=global_X_ax_label_shift + 0.1)

# NOTE: Tight layout often produces nice results but requires the title to be spaced accordingly
# CAUTION: as far as this function (windrose-subplotting) is concerned, it hasn't been necessary (status: 17-08-2019)
if len(df_plot_list) == 1:
    pass
else:  # in case of subplots
    # * FINALLY, set legend to None due to the subplots character
    legend = None

## ** Finally, either show or save the current plot/figure **
aux_plot.show_or_save_plot(fig=fig,
                           path=savepath,
                           basename=titlestr,
                           file_extensions=['.png', '.pdf'],
                           legend=legend)

我最近遇到了同样的错误信息,和你在使用 fig.savefig 时弹出的信息一样。我认为问题可能出现在代码的较早部分,而不是 savefig 函数本身。对于我的情节,我将问题追溯到 plt.scatter() 中的 now-deprecated 参数 - 我使用了 edgecolors='',现在应该是 edgecolors=None,它导致了相同的错误消息'ValueError: Expected 2-dimensional array, got 1' 当我试图保存这个数字时。

例如,此代码块会引发错误,但如果将 edgecolors 参数更改为 =None,代码将正常运行。

fig = plt.figure()
a = [1,2,3,4]
plt.scatter(a,a,edgecolors='')
fig.savefig('test.png')

不知道你在策划的时候有没有用过类似的弃用参数?通过在 ipython 中做一个小测试图来追溯是最容易的,因为弃用警告以一种在简单执行 .py 文件时不会出现的方式正确引发。

编辑:刚刚发现您在底部包含了您的代码 - 我相信您确实遇到了同样的问题,您在调用 fill_between

时使用了 edgecolors=""