Skip to content
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ including other versions of pandas.

Other Enhancements
^^^^^^^^^^^^^^^^^^

- :func:`DataFrame.plot` keywords ``logy``, ``logx`` and ``loglog`` can now accept the value ``'sym'`` for symlog scaling. (:issue:`24867`)
- Indexing of ``DataFrame`` and ``Series`` now accepts zerodim ``np.ndarray`` (:issue:`24919`)
- :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`)
- :meth:`DataFrame.at_time` and :meth:`Series.at_time` now support :meth:`datetime.time` objects with timezones (:issue:`24043`)
Expand Down
15 changes: 13 additions & 2 deletions pandas/plotting/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,21 @@ def _setup_subplots(self):

axes = _flatten(axes)

if self.logx or self.loglog:
valid_log = {False, True, 'sym', None}
input_log = {self.logx, self.logy, self.loglog}
if input_log - valid_log:
raise ValueError(f"Valid inputs are boolean, None and 'sym'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't use f-strings yet, unfortunately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, changed! thanks! @TomAugspurger

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May need to push these changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, i am really really sorry... i thought i successfully pushed the change before rushing home @TomAugspurger

f", {i} is given.")

if self.logx is True or self.loglog is True:
[a.set_xscale('log') for a in axes]
if self.logy or self.loglog:
elif self.logx == 'sym' or self.loglog == 'sym':
[a.set_xscale('symlog') for a in axes]

if self.logy is True or self.loglog is True:
[a.set_yscale('log') for a in axes]
elif self.logy == 'sym' or self.loglog == 'sym':
[a.set_yscale('symlog') for a in axes]

self.fig = fig
self.axes = axes
Expand Down
28 changes: 28 additions & 0 deletions pandas/tests/plotting/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,42 @@ def test_plot_xy(self):
@pytest.mark.slow
def test_logscales(self):
df = DataFrame({'a': np.arange(100)}, index=np.arange(100))

ax = df.plot(logy=True)
self._check_ax_scales(ax, yaxis='log')
assert ax.get_yscale() == 'log'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than these individual checks can you parametrize all of the combinations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! @WillAyd i parametrize the combinations.


ax = df.plot(logy='sym')
self._check_ax_scales(ax, yaxis='symlog')
assert ax.get_yscale() == 'symlog'

ax = df.plot(logx=True)
self._check_ax_scales(ax, xaxis='log')
assert ax.get_xscale() == 'log'

ax = df.plot(logx='sym')
self._check_ax_scales(ax, xaxis='symlog')
assert ax.get_xscale() == 'symlog'

ax = df.plot(loglog=True)
self._check_ax_scales(ax, xaxis='log', yaxis='log')
assert ax.get_xscale() == 'log'
assert ax.get_yscale() == 'log'

ax = df.plot(loglog='sym')
self._check_ax_scales(ax, xaxis='symlog', yaxis='symlog')
assert ax.get_xscale() == 'symlog'
assert ax.get_yscale() == 'symlog'

@pytest.mark.parametrize("wrong_input", ["sm", "symlog"])
@pytest.mark.parametrize("input_param", ["logx", "logy", "loglog"])
def test_invalid_logscale(self, wrong_input, input_param):
# GH: 24867
df = DataFrame({'a': np.arange(100)}, index=np.arange(100))

msg = "Valid inputs are boolean, None and 'sym'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the match msg to ensure that the bad parameter is included. You can remove the "wrong_input" fixture I think, and just test one bad input.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated!

with pytest.raises(ValueError, match=msg):
df.plot(**{input_param: wrong_input})

@pytest.mark.slow
def test_xcompat(self):
Expand Down