matplotlib bar源碼- 繪製柱狀圖

    def bar(self, *args, **kwargs):
        r"""
        Make a bar plot.

        Call signatures::

           bar(x, height, *, align='center', **kwargs)
           bar(x, height, width, *, align='center', **kwargs)
           bar(x, height, width, bottom, *, align='center', **kwargs)

        The bars are positioned at *x* with the given *align* ment. Their
        dimensions are given by *width* and *height*. The vertical baseline
        is *bottom* (default 0).

        Each of *x*, *height*, *width*, and *bottom* may either be a scalar
        applying to all bars, or it may be a sequence of length N providing a
        separate value for each bar.


        Parameters
        ----------
        x : sequence of scalars
            The x coordinates of the bars. See also *align* for the
            alignment of the bars to the coordinates.

        height : scalar or sequence of scalars
            The height(s) of the bars.

        width : scalar or array-like, optional
            The width(s) of the bars (default: 0.8).

        bottom : scalar or array-like, optional
            The y coordinate(s) of the bars bases (default: 0).

        align : {'center', 'edge'}, optional, default: 'center'
            Alignment of the bars to the *x* coordinates:

            - 'center': Center the base on the *x* positions.
            - 'edge': Align the left edges of the bars with the *x* positions.

            To align the bars on the right edge pass a negative *width* and
            ``align='edge'``.

        Returns
        -------
        container : `.BarContainer`
            Container with all the bars and optionally errorbars.

        Other Parameters
        ----------------
        color : scalar or array-like, optional
            The colors of the bar faces.

        edgecolor : scalar or array-like, optional
            The colors of the bar edges.

        linewidth : scalar or array-like, optional
            Width of the bar edge(s). If 0, don't draw edges.

        tick_label : string or array-like, optional
            The tick labels of the bars.
            Default: None (Use default numeric labels.)

        xerr, yerr : scalar or array-like of shape(N,) or shape(2,N), optional
            If not *None*, add horizontal / vertical errorbars to the bar tips.
            The values are +/- sizes relative to the data:

            - scalar: symmetric +/- values for all bars
            - shape(N,): symmetric +/- values for each bar
            - shape(2,N): Separate - and + values for each bar. First row
                contains the lower errors, the second row contains the
                upper errors.
            - *None*: No errorbar. (Default)

            See :doc:`/gallery/statistics/errorbar_features`
            for an example on the usage of ``xerr`` and ``yerr``.

        ecolor : scalar or array-like, optional, default: 'black'
            The line color of the errorbars.

        capsize : scalar, optional
           The length of the error bar caps in points.
           Default: None, which will take the value from
           :rc:`errorbar.capsize`.

        error_kw : dict, optional
            Dictionary of kwargs to be passed to the `~.Axes.errorbar`
            method. Values of *ecolor* or *capsize* defined here take
            precedence over the independent kwargs.

        log : bool, optional, default: False
            If *True*, set the y-axis to be log scale.

        orientation : {'vertical',  'horizontal'}, optional
            *This is for internal use only.* Please use `barh` for
            horizontal bar plots. Default: 'vertical'.

        See also
        --------
        barh: Plot a horizontal bar plot.

        Notes
        -----
        The optional arguments *color*, *edgecolor*, *linewidth*,
        *xerr*, and *yerr* can be either scalars or sequences of
        length equal to the number of bars.  This enables you to use
        bar as the basis for stacked bar charts, or candlestick plots.
        Detail: *xerr* and *yerr* are passed directly to
        :meth:`errorbar`, so they can also have shape 2xN for
        independent specification of lower and upper errors.

        Other optional kwargs:

        %(Rectangle)s

        """
        kwargs = cbook.normalize_kwargs(kwargs, mpatches._patch_alias_map)
        # this is using the lambdas to do the arg/kwarg unpacking rather
        # than trying to re-implement all of that logic our selves.
        matchers = [
            (lambda x, height, width=0.8, bottom=None, **kwargs:
             (False, x, height, width, bottom, kwargs)),
            (lambda left, height, width=0.8, bottom=None, **kwargs:
             (True, left, height, width, bottom, kwargs)),
        ]
        exps = []
        for matcher in matchers:
            try:
                dp, x, height, width, y, kwargs = matcher(*args, **kwargs)
            except TypeError as e:
                # This can only come from a no-match as there is
                # no other logic in the matchers.
                exps.append(e)
            else:
                break
        else:
            raise exps[0]
        # if we matched the second-case, then the user passed in
        # left=val as a kwarg which we want to deprecate
        if dp:
            warnings.warn(
                "The *left* kwarg to `bar` is deprecated use *x* instead. "
                "Support for *left* will be removed in Matplotlib 3.0",
                mplDeprecation, stacklevel=2)
        if not self._hold:
            self.cla()
        color = kwargs.pop('color', None)
        if color is None:
            color = self._get_patches_for_fill.get_next_color()
        edgecolor = kwargs.pop('edgecolor', None)
        linewidth = kwargs.pop('linewidth', None)

        # Because xerr and yerr will be passed to errorbar,
        # most dimension checking and processing will be left
        # to the errorbar method.
        xerr = kwargs.pop('xerr', None)
        yerr = kwargs.pop('yerr', None)
        error_kw = kwargs.pop('error_kw', dict())
        ecolor = kwargs.pop('ecolor', 'k')
        capsize = kwargs.pop('capsize', rcParams["errorbar.capsize"])
        error_kw.setdefault('ecolor', ecolor)
        error_kw.setdefault('capsize', capsize)

        if rcParams['_internal.classic_mode']:
            align = kwargs.pop('align', 'edge')
        else:
            align = kwargs.pop('align', 'center')

        orientation = kwargs.pop('orientation', 'vertical')
        log = kwargs.pop('log', False)
        label = kwargs.pop('label', '')
        tick_labels = kwargs.pop('tick_label', None)

        adjust_ylim = False
        adjust_xlim = False

        if orientation == 'vertical':
            if y is None:
                if self.get_yscale() == 'log':
                    adjust_ylim = True
                y = 0

        elif orientation == 'horizontal':
            if x is None:
                if self.get_xscale() == 'log':
                    adjust_xlim = True
                x = 0

        if orientation == 'vertical':
            self._process_unit_info(xdata=x, ydata=height, kwargs=kwargs)
            if log:
                self.set_yscale('log', nonposy='clip')
        elif orientation == 'horizontal':
            self._process_unit_info(xdata=width, ydata=y, kwargs=kwargs)
            if log:
                self.set_xscale('log', nonposx='clip')
        else:
            raise ValueError('invalid orientation: %s' % orientation)

        # lets do some conversions now since some types cannot be
        # subtracted uniformly
        if self.xaxis is not None:
            x = self.convert_xunits(x)
            width = self.convert_xunits(width)
            if xerr is not None:
                xerr = self.convert_xunits(xerr)

        if self.yaxis is not None:
            y = self.convert_yunits(y)
            height = self.convert_yunits(height)
            if yerr is not None:
                yerr = self.convert_yunits(yerr)

        x, height, width, y, linewidth = np.broadcast_arrays(
            # Make args iterable too.
            np.atleast_1d(x), height, width, y, linewidth)

        # Now that units have been converted, set the tick locations.
        if orientation == 'vertical':
            tick_label_axis = self.xaxis
            tick_label_position = x
        elif orientation == 'horizontal':
            tick_label_axis = self.yaxis
            tick_label_position = y

        linewidth = itertools.cycle(np.atleast_1d(linewidth))
        color = itertools.chain(itertools.cycle(mcolors.to_rgba_array(color)),
                                # Fallback if color == "none".
                                itertools.repeat([0, 0, 0, 0]))
        if edgecolor is None:
            edgecolor = itertools.repeat(None)
        else:
            edgecolor = itertools.chain(
                itertools.cycle(mcolors.to_rgba_array(edgecolor)),
                # Fallback if edgecolor == "none".
                itertools.repeat([0, 0, 0, 0]))

        # We will now resolve the alignment and really have
        # left, bottom, width, height vectors
        if align == 'center':
            if orientation == 'vertical':
                left = x - width / 2
                bottom = y
            elif orientation == 'horizontal':
                bottom = y - height / 2
                left = x
        elif align == 'edge':
            left = x
            bottom = y
        else:
            raise ValueError('invalid alignment: %s' % align)

        patches = []
        args = zip(left, bottom, width, height, color, edgecolor, linewidth)
        for l, b, w, h, c, e, lw in args:
            r = mpatches.Rectangle(
                xy=(l, b), width=w, height=h,
                facecolor=c,
                edgecolor=e,
                linewidth=lw,
                label='_nolegend_',
                )
            r.update(kwargs)
            r.get_path()._interpolation_steps = 100
            if orientation == 'vertical':
                r.sticky_edges.y.append(b)
            elif orientation == 'horizontal':
                r.sticky_edges.x.append(l)
            self.add_patch(r)
            patches.append(r)

        holdstate = self._hold
        self._hold = True  # ensure hold is on before plotting errorbars

        if xerr is not None or yerr is not None:
            if orientation == 'vertical':
                # using list comps rather than arrays to preserve unit info
                ex = [l + 0.5 * w for l, w in zip(left, width)]
                ey = [b + h for b, h in zip(bottom, height)]

            elif orientation == 'horizontal':
                # using list comps rather than arrays to preserve unit info
                ex = [l + w for l, w in zip(left, width)]
                ey = [b + 0.5 * h for b, h in zip(bottom, height)]

            error_kw.setdefault("label", '_nolegend_')

            errorbar = self.errorbar(ex, ey,
                                     yerr=yerr, xerr=xerr,
                                     fmt='none', **error_kw)
        else:
            errorbar = None

        self._hold = holdstate  # restore previous hold state

        if adjust_xlim:
            xmin, xmax = self.dataLim.intervalx
            xmin = min(w for w in width if w > 0)
            if xerr is not None:
                xmin = xmin - np.max(xerr)
            xmin = max(xmin * 0.9, 1e-100)
            self.dataLim.intervalx = (xmin, xmax)

        if adjust_ylim:
            ymin, ymax = self.dataLim.intervaly
            ymin = min(h for h in height if h > 0)
            if yerr is not None:
                ymin = ymin - np.max(yerr)
            ymin = max(ymin * 0.9, 1e-100)
            self.dataLim.intervaly = (ymin, ymax)
        self.autoscale_view()

        bar_container = BarContainer(patches, errorbar, label=label)
        self.add_container(bar_container)

        if tick_labels is not None:
            tick_labels = _backports.broadcast_to(tick_labels, len(patches))
            tick_label_axis.set_ticks(tick_label_position)
            tick_label_axis.set_ticklabels(tick_labels)

        return bar_container

    @docstring.dedent_interpd
    def barh(self, *args, **kwargs):
        r"""
        Make a horizontal bar plot.

        Call signatures::

           bar(y, width, *, align='center', **kwargs)
           bar(y, width, height, *, align='center', **kwargs)
           bar(y, width, height, left, *, align='center', **kwargs)

        The bars are positioned at *y* with the given *align*. Their
        dimensions are given by *width* and *height*. The horizontal baseline
        is *left* (default 0).

        Each of *y*, *width*, *height*, and *left* may either be a scalar
        applying to all bars, or it may be a sequence of length N providing a
        separate value for each bar.


        Parameters
        ----------
        y : scalar or array-like
            The y coordinates of the bars. See also *align* for the
            alignment of the bars to the coordinates.

        width : scalar or array-like
            The width(s) of the bars.

        height : sequence of scalars, optional, default: 0.8
            The heights of the bars.

        left : sequence of scalars
            The x coordinates of the left sides of the bars (default: 0).

        align : {'center', 'edge'}, optional, default: 'center'
            Alignment of the base to the *y* coordinates*:

            - 'center': Center the bars on the *y* positions.
            - 'edge': Align the bottom edges of the bars with the *y*
              positions.

            To align the bars on the top edge pass a negative *height* and
            ``align='edge'``.

        Returns
        -------
        container : `.BarContainer`
            Container with all the bars and optionally errorbars.

        Other Parameters
        ----------------
        color : scalar or array-like, optional
            The colors of the bar faces.

        edgecolor : scalar or array-like, optional
            The colors of the bar edges.

        linewidth : scalar or array-like, optional
            Width of the bar edge(s). If 0, don't draw edges.

        tick_label : string or array-like, optional
            The tick labels of the bars.
            Default: None (Use default numeric labels.)

        xerr, yerr : scalar or array-like of shape(N,) or shape(2,N), optional
            If not ``None``, add horizontal / vertical errorbars to the
            bar tips. The values are +/- sizes relative to the data:

            - scalar: symmetric +/- values for all bars
            - shape(N,): symmetric +/- values for each bar
            - shape(2,N): Separate - and + values for each bar. First row
                contains the lower errors, the second row contains the
                upper errors.
            - *None*: No errorbar. (default)

            See :doc:`/gallery/statistics/errorbar_features`
            for an example on the usage of ``xerr`` and ``yerr``.

        ecolor : scalar or array-like, optional, default: 'black'
            The line color of the errorbars.

        capsize : scalar, optional
           The length of the error bar caps in points.
           Default: None, which will take the value from
           :rc:`errorbar.capsize`.

        error_kw : dict, optional
            Dictionary of kwargs to be passed to the `~.Axes.errorbar`
            method. Values of *ecolor* or *capsize* defined here take
            precedence over the independent kwargs.

        log : bool, optional, default: False
            If ``True``, set the x-axis to be log scale.

        See also
        --------
        bar: Plot a vertical bar plot.

        Notes
        -----
        The optional arguments *color*, *edgecolor*, *linewidth*,
        *xerr*, and *yerr* can be either scalars or sequences of
        length equal to the number of bars.  This enables you to use
        bar as the basis for stacked bar charts, or candlestick plots.
        Detail: *xerr* and *yerr* are passed directly to
        :meth:`errorbar`, so they can also have shape 2xN for
        independent specification of lower and upper errors.

        Other optional kwargs:

        %(Rectangle)s

        """
        # this is using the lambdas to do the arg/kwarg unpacking rather
        # than trying to re-implement all of that logic our selves.
        matchers = [
            (lambda y, width, height=0.8, left=None, **kwargs:
             (False, y, width, height, left, kwargs)),
            (lambda bottom, width, height=0.8, left=None, **kwargs:
             (True, bottom, width, height, left, kwargs)),
        ]
        excs = []
        for matcher in matchers:
            try:
                dp, y, width, height, left, kwargs = matcher(*args, **kwargs)
            except TypeError as e:
                # This can only come from a no-match as there is
                # no other logic in the matchers.
                excs.append(e)
            else:
                break
        else:
            raise excs[0]

        if dp:
            warnings.warn(
                "The *bottom* kwarg to `barh` is deprecated use *y* instead. "
                "Support for *bottom* will be removed in Matplotlib 3.0",
                mplDeprecation, stacklevel=2)
        kwargs.setdefault('orientation', 'horizontal')
        patches = self.bar(x=left, height=height, width=width,
                           bottom=y, **kwargs)
        return patches

    @_preprocess_data(label_namer=None)
    @docstring.dedent_interpd
    def broken_barh(self, xranges, yrange, **kwargs):
        """
        Plot a horizontal sequence of rectangles.

        A rectangle is drawn for each element of *xranges*. All rectangles
        have the same vertical position and size defined by *yrange*.

        This is a convenience function for instantiating a
        `.BrokenBarHCollection`, adding it to the axes and autoscaling the
        view.

        Parameters
        ----------
        xranges : sequence of tuples (*xmin*, *xwidth*)
            The x-positions and extends of the rectangles. For each tuple
            (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* +
            *xwidth*.
        yranges : (*ymin*, *ymax*)
            The y-position and extend for all the rectangles.

        Other Parameters
        ----------------
        **kwargs : :class:`.BrokenBarHCollection` properties

            Each *kwarg* can be either a single argument applying to all
            rectangles, e.g.::

                facecolors='black'

            or a sequence of arguments over which is cycled, e.g.::

                facecolors=('black', 'blue')

            would create interleaving black and blue rectangles.

            Supported keywords:

            %(BrokenBarHCollection)s

        Returns
        -------
        collection : A :class:`~.collections.BrokenBarHCollection`

        Notes
        -----
        .. [Notes section required for data comment. See #10189.]

        """
        # process the unit information
        if len(xranges):
            xdata = cbook.safe_first_element(xranges)
        else:
            xdata = None
        if len(yrange):
            ydata = cbook.safe_first_element(yrange)
        else:
            ydata = None
        self._process_unit_info(xdata=xdata,
                                ydata=ydata,
                                kwargs=kwargs)
        xranges = self.convert_xunits(xranges)
        yrange = self.convert_yunits(yrange)

        col = mcoll.BrokenBarHCollection(xranges, yrange, **kwargs)
        self.add_collection(col, autolim=True)
        self.autoscale_view()

        return col

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章