Skip to content

Commit f66246e

Browse files
authored
REF: avoid altering self.data in get_xticks (#55906)
* REF: avoid altering self.data in get_xticks * GH ref
1 parent d9c7b50 commit f66246e

File tree

2 files changed

+26
-21
lines changed

2 files changed

+26
-21
lines changed

pandas/plotting/_matplotlib/core.py

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,13 @@
4646
)
4747
from pandas.core.dtypes.generic import (
4848
ABCDataFrame,
49+
ABCDatetimeIndex,
4950
ABCIndex,
5051
ABCMultiIndex,
5152
ABCPeriodIndex,
5253
ABCSeries,
5354
)
54-
from pandas.core.dtypes.missing import (
55-
isna,
56-
notna,
57-
)
55+
from pandas.core.dtypes.missing import isna
5856

5957
import pandas.core.common as com
6058
from pandas.core.frame import DataFrame
@@ -95,10 +93,7 @@
9593
npt,
9694
)
9795

98-
from pandas import (
99-
PeriodIndex,
100-
Series,
101-
)
96+
from pandas import Series
10297

10398

10499
def _color_in_style(style: str) -> bool:
@@ -888,26 +883,25 @@ def plt(self):
888883
_need_to_set_index = False
889884

890885
@final
891-
def _get_xticks(self, convert_period: bool = False):
886+
def _get_xticks(self):
892887
index = self.data.index
893888
is_datetype = index.inferred_type in ("datetime", "date", "datetime64", "time")
894889

895890
x: list[int] | np.ndarray
896891
if self.use_index:
897-
if convert_period and isinstance(index, ABCPeriodIndex):
898-
self.data = self.data.reindex(index=index.sort_values())
899-
index = cast("PeriodIndex", self.data.index)
892+
if isinstance(index, ABCPeriodIndex):
893+
# test_mixed_freq_irreg_period
900894
x = index.to_timestamp()._mpl_repr()
895+
# TODO: why do we need to do to_timestamp() here but not other
896+
# places where we call mpl_repr?
901897
elif is_any_real_numeric_dtype(index.dtype):
902898
# Matplotlib supports numeric values or datetime objects as
903899
# xaxis values. Taking LBYL approach here, by the time
904900
# matplotlib raises exception when using non numeric/datetime
905901
# values for xaxis, several actions are already taken by plt.
906902
x = index._mpl_repr()
907-
elif is_datetype:
908-
self.data = self.data[notna(self.data.index)]
909-
self.data = self.data.sort_index()
910-
x = self.data.index._mpl_repr()
903+
elif isinstance(index, ABCDatetimeIndex) or is_datetype:
904+
x = index._mpl_repr()
911905
else:
912906
self._need_to_set_index = True
913907
x = list(range(len(index)))
@@ -1469,7 +1463,7 @@ def _make_plot(self, fig: Figure) -> None:
14691463
plotf = self._ts_plot
14701464
it = data.items()
14711465
else:
1472-
x = self._get_xticks(convert_period=True)
1466+
x = self._get_xticks()
14731467
# error: Incompatible types in assignment (expression has type
14741468
# "Callable[[Any, Any, Any, Any, Any, Any, KwArg(Any)], Any]", variable has
14751469
# type "Callable[[Any, Any, Any, Any, KwArg(Any)], Any]")

pandas/tests/plotting/frame/test_frame.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,16 +1362,27 @@ def test_specified_props_kwd_plot_box(self, props, expected):
13621362
assert result[expected][0].get_color() == "C1"
13631363

13641364
def test_unordered_ts(self):
1365+
# GH#2609, GH#55906
1366+
index = [date(2012, 10, 1), date(2012, 9, 1), date(2012, 8, 1)]
1367+
values = [3.0, 2.0, 1.0]
13651368
df = DataFrame(
1366-
np.array([3.0, 2.0, 1.0]),
1367-
index=[date(2012, 10, 1), date(2012, 9, 1), date(2012, 8, 1)],
1369+
np.array(values),
1370+
index=index,
13681371
columns=["test"],
13691372
)
13701373
ax = df.plot()
13711374
xticks = ax.lines[0].get_xdata()
1372-
assert xticks[0] < xticks[1]
1375+
tm.assert_numpy_array_equal(xticks, np.array(index, dtype=object))
13731376
ydata = ax.lines[0].get_ydata()
1374-
tm.assert_numpy_array_equal(ydata, np.array([1.0, 2.0, 3.0]))
1377+
tm.assert_numpy_array_equal(ydata, np.array(values))
1378+
1379+
# even though we don't sort the data before passing it to matplotlib,
1380+
# the ticks are sorted
1381+
xticks = ax.xaxis.get_ticklabels()
1382+
xlocs = [x.get_position()[0] for x in xticks]
1383+
assert pd.Index(xlocs).is_monotonic_increasing
1384+
xlabels = [x.get_text() for x in xticks]
1385+
assert pd.to_datetime(xlabels, format="%Y-%m-%d").is_monotonic_increasing
13751386

13761387
@pytest.mark.parametrize("kind", plotting.PlotAccessor._common_kinds)
13771388
def test_kind_both_ways(self, kind):

0 commit comments

Comments
 (0)