diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 5b955aa45219a..2b961f88b6e75 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -797,6 +797,7 @@ Plotting ^^^^^^^^ - Bug in :meth:`DataFrame.plot.box` with ``vert=False`` and a Matplotlib ``Axes`` created with ``sharey=True`` (:issue:`54941`) - Bug in :meth:`DataFrame.plot.scatter` discarding string columns (:issue:`56142`) +- Bug in :meth:`DataFrame.plot` where bar and line plots are not aligned on the x-axis (:issue:`56611`) - Bug in :meth:`Series.plot` when reusing an ``ax`` object failing to raise when a ``how`` keyword is passed (:issue:`55953`) Groupby/resample/rolling diff --git a/pandas/plotting/_matplotlib/core.py b/pandas/plotting/_matplotlib/core.py index 2979903edf360..e811411e8f1d6 100644 --- a/pandas/plotting/_matplotlib/core.py +++ b/pandas/plotting/_matplotlib/core.py @@ -1805,6 +1805,15 @@ def _kind(self) -> Literal["bar", "barh"]: def orientation(self) -> PlottingOrientation: return "vertical" + @final + def _is_ts_plot(self) -> bool: + # this is slightly deceptive + return not self.x_compat and self.use_index and self._use_dynamic_x() + + @final + def _use_dynamic_x(self) -> bool: + return use_dynamic_x(self._get_ax(0), self.data) + def __init__( self, data, @@ -1823,7 +1832,6 @@ def __init__( self.bar_width = width self._align = align self._position = position - self.tick_pos = np.arange(len(data)) if is_list_like(bottom): bottom = np.array(bottom) @@ -1836,6 +1844,12 @@ def __init__( MPLPlot.__init__(self, data, **kwargs) + self.tick_pos = ( + np.array(self._get_xticks(), dtype=int) + if (self._is_series and not self._is_ts_plot) + else np.arange(len(data)) + ) + @cache_readonly def ax_pos(self) -> np.ndarray: return self.tick_pos - self.tickoffset