Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3ae8f9c

Browse files
committed
Automatically create tick formatters for str and callable inputs.
1 parent 5e74fb4 commit 3ae8f9c

File tree

6 files changed

+139
-36
lines changed

6 files changed

+139
-36
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Allow tick formatters to be set with str or function inputs
2+
------------------------------------------------------------------------
3+
`~.Axis.set_major_formatter` and `~.Axis.set_minor_formatter`
4+
now accept `str` or function inputs in addition to `~.ticker.Formatter`
5+
instances. For a `str` a `~.ticker.StrMethodFormatter` is automatically
6+
created and used. For a function a `~.ticker.FuncFormatter` is automatically
7+
created and used.

examples/ticks_and_spines/tick-formatters.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def setup(ax, title):
3434
fontsize=14, fontname='Monospace', color='tab:blue')
3535

3636

37-
fig, axs = plt.subplots(7, 1, figsize=(8, 6))
37+
fig, axs = plt.subplots(9, 1, figsize=(8, 8))
3838

3939
# Null formatter
4040
setup(axs[0], title="NullFormatter()")
@@ -59,21 +59,30 @@ def major_formatter(x, pos):
5959
setup(axs[2], title='FuncFormatter(lambda x, pos: "[%.2f]" % x)')
6060
axs[2].xaxis.set_major_formatter(major_formatter)
6161

62-
# FormatStr formatter
63-
setup(axs[3], title="FormatStrFormatter('#%d')")
64-
axs[3].xaxis.set_major_formatter(ticker.FormatStrFormatter("#%d"))
62+
# FuncFormatter can be automatically created directly with a function input
63+
# without needing to manually create the formatter
64+
setup(axs[3], title="lambda x, pos: str(x-5)")
65+
axs[3].xaxis.set_major_formatter(lambda x, pos: str(x-5))
66+
67+
# StrMethod formatter
68+
setup(axs[4], title="StrMethodFormatter('{x:.3f}')")
69+
axs[4].xaxis.set_major_formatter(ticker.StrMethodFormatter("{x:.3f}"))
70+
71+
# StrMethodFormatter can also be created directly with a string input.
72+
setup(axs[5], title="'{x} km'")
73+
axs[5].xaxis.set_major_formatter('{x} km')
6574

6675
# Scalar formatter
67-
setup(axs[4], title="ScalarFormatter()")
68-
axs[4].xaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True))
76+
setup(axs[6], title="ScalarFormatter()")
77+
axs[6].xaxis.set_major_formatter(ticker.ScalarFormatter(useMathText=True))
6978

70-
# StrMethod formatter
71-
setup(axs[5], title="StrMethodFormatter('{x:.3f}')")
72-
axs[5].xaxis.set_major_formatter(ticker.StrMethodFormatter("{x:.3f}"))
79+
# FormatStr formatter
80+
setup(axs[7], title="FormatStrFormatter('#%d')")
81+
axs[7].xaxis.set_major_formatter(ticker.FormatStrFormatter("#%d"))
7382

7483
# Percent formatter
75-
setup(axs[6], title="PercentFormatter(xmax=5)")
76-
axs[6].xaxis.set_major_formatter(ticker.PercentFormatter(xmax=5))
84+
setup(axs[8], title="PercentFormatter(xmax=5)")
85+
axs[8].xaxis.set_major_formatter(ticker.PercentFormatter(xmax=5))
7786

7887
plt.tight_layout()
7988
plt.show()

lib/matplotlib/axis.py

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,37 +1515,93 @@ def set_major_formatter(self, formatter):
15151515
"""
15161516
Set the formatter of the major ticker.
15171517
1518+
In addition to a `~matplotlib.ticker.Formatter` instance,
1519+
this also accepts a `str` or function.
1520+
1521+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1522+
The field used for the value must be labeled *x* and the field used
1523+
for the position must be labeled *pos*.
1524+
1525+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1526+
The function should take in two inputs (a tick value ``x`` and a
1527+
position ``pos``), and return a string containing the corresponding
1528+
tick label.
1529+
15181530
Parameters
15191531
----------
1520-
formatter : `~matplotlib.ticker.Formatter`
1532+
formatter : `~matplotlib.ticker.Formatter`, str, or function
15211533
"""
1522-
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1523-
if (isinstance(formatter, mticker.FixedFormatter)
1524-
and len(formatter.seq) > 0
1525-
and not isinstance(self.major.locator, mticker.FixedLocator)):
1526-
cbook._warn_external('FixedFormatter should only be used together '
1527-
'with FixedLocator')
1528-
self.isDefault_majfmt = False
1529-
self.major.formatter = formatter
1530-
formatter.set_axis(self)
1531-
self.stale = True
1534+
self._set_formatter(formatter, self.major)
15321535

15331536
def set_minor_formatter(self, formatter):
15341537
"""
15351538
Set the formatter of the minor ticker.
15361539
1540+
In addition to a `~matplotlib.ticker.Formatter` instance,
1541+
this also accepts a `str` or function.
1542+
1543+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1544+
The field used for the tick value must be labeled *x* and the field
1545+
used for the tick position must be labeled *pos*.
1546+
See the `~matplotlib.ticker.StrMethodFormatter` documentation for
1547+
more information.
1548+
1549+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1550+
The function should take in two inputs (a tick value ``x`` and a
1551+
position ``pos``), and return a string containing the corresponding
1552+
tick label.
1553+
See the `~matplotlib.ticker.FuncFormatter` documentation for
1554+
more information.
1555+
15371556
Parameters
15381557
----------
1539-
formatter : `~matplotlib.ticker.Formatter`
1558+
formatter : `~matplotlib.ticker.Formatter`, str, or function
15401559
"""
1541-
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1560+
self._set_formatter(formatter, self.minor)
1561+
1562+
def _set_formatter(self, formatter, level):
1563+
"""
1564+
Set the formatter of the major or minor ticker.
1565+
1566+
In addition to a `~matplotlib.ticker.Formatter` instance,
1567+
this also accepts a `str` or function.
1568+
1569+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1570+
The field used for the value must be labeled *x* and the field used
1571+
for the position must be labeled *pos*.
1572+
1573+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1574+
The function should take in two inputs (a tick value ``x`` and a
1575+
position ``pos``), and return a string containing the corresponding
1576+
tick label.
1577+
1578+
Parameters
1579+
----------
1580+
formatter : `~matplotlib.ticker.Formatter`, str, or function
1581+
level : `self.major` or `self.minor`
1582+
"""
1583+
if isinstance(formatter, str):
1584+
formatter = mticker.StrMethodFormatter(formatter)
1585+
# Don't allow any other TickHelper to avoid easy-to-make errors,
1586+
# like using a Locator instead of a Formatter.
1587+
elif (callable(formatter) and
1588+
not isinstance(formatter, mticker.TickHelper)):
1589+
formatter = mticker.FuncFormatter(formatter)
1590+
else:
1591+
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1592+
15421593
if (isinstance(formatter, mticker.FixedFormatter)
15431594
and len(formatter.seq) > 0
1544-
and not isinstance(self.minor.locator, mticker.FixedLocator)):
1595+
and not isinstance(level.locator, mticker.FixedLocator)):
15451596
cbook._warn_external('FixedFormatter should only be used together '
15461597
'with FixedLocator')
1547-
self.isDefault_minfmt = False
1548-
self.minor.formatter = formatter
1598+
1599+
if level == self.major:
1600+
self.isDefault_majfmt = False
1601+
else:
1602+
self.isDefault_minfmt = False
1603+
1604+
level.formatter = formatter
15491605
formatter.set_axis(self)
15501606
self.stale = True
15511607

lib/matplotlib/tests/test_axes.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,28 @@ def test_formatter_ticker():
204204
ax.autoscale_view()
205205

206206

207+
def test_auto_formatter():
208+
def _formfunc(x, pos):
209+
return ''
210+
211+
formstr = '{x}_{pos}'
212+
213+
ax = plt.figure().subplots()
214+
ax.xaxis.set_major_formatter(_formfunc)
215+
ax.yaxis.set_minor_formatter(formstr)
216+
217+
targ_funcformatter = mticker.FuncFormatter(_formfunc)
218+
targ_strformatter = mticker.StrMethodFormatter(formstr)
219+
220+
assert isinstance(ax.xaxis.get_major_formatter(),
221+
mticker.FuncFormatter)
222+
assert isinstance(ax.yaxis.get_minor_formatter(),
223+
mticker.StrMethodFormatter)
224+
225+
assert ax.xaxis.get_major_formatter().func == targ_funcformatter.func
226+
assert ax.yaxis.get_minor_formatter().fmt == targ_strformatter.fmt
227+
228+
207229
@image_comparison(["twin_axis_locators_formatters"])
208230
def test_twin_axis_locators_formatters():
209231
vals = np.linspace(0, 1, num=5, endpoint=True)

lib/matplotlib/ticker.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@
159159
ax.yaxis.set_major_formatter(ymajor_formatter)
160160
ax.yaxis.set_minor_formatter(yminor_formatter)
161161
162+
For `.StrMethodFormatter`, `~.Axis.set_major_formatter` and
163+
`~.Axis.set_minor_formatter` accept a ``str``. In that case a
164+
`.StrMethodFormatter` will be automatically created and applied based on
165+
the given ``str``. Similalry, a `.FuncFormatter` will be automatically
166+
created and applied if a function is provided.
167+
162168
See :doc:`/gallery/ticks_and_spines/major_minor_demo` for an
163169
example of setting major and minor ticks. See the :mod:`matplotlib.dates`
164170
module for more information and examples of using date locators and formatters.
@@ -415,8 +421,8 @@ class StrMethodFormatter(Formatter):
415421
"""
416422
Use a new-style format string (as used by `str.format`) to format the tick.
417423
418-
The field used for the value must be labeled *x* and the field used
419-
for the position must be labeled *pos*.
424+
The field used for the tick value must be labeled *x* and the field used
425+
for the tick position must be labeled *pos*.
420426
"""
421427
def __init__(self, fmt):
422428
self.fmt = fmt

tutorials/text/text_intro.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,25 +291,26 @@
291291
axs[0].plot(x1, y1)
292292
axs[1].plot(x1, y1)
293293
ticks = np.arange(0., 8.1, 2.)
294-
# list comprehension to get all tick labels...
295294
formatter = matplotlib.ticker.StrMethodFormatter('{x:1.1f}')
296295
axs[1].xaxis.set_ticks(ticks)
297296
axs[1].xaxis.set_major_formatter(formatter)
298297
axs[1].set_xlim(axs[0].get_xlim())
299298
plt.show()
300299

301300
#############################################################################
301+
# A `matplotlib.ticker.StrMethodFormatter` can also be created by simply
302+
# passing a ``str`` without having to explicitly create the formatter.
303+
#
302304
# And of course we could have used a non-default locator to set the
303305
# tick locations. Note we still pass in the tick values, but the
304306
# x-limit fix used above is *not* needed.
305307

306308
fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
307309
axs[0].plot(x1, y1)
308310
axs[1].plot(x1, y1)
309-
formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
310311
locator = matplotlib.ticker.FixedLocator(ticks)
311312
axs[1].xaxis.set_major_locator(locator)
312-
axs[1].xaxis.set_major_formatter(formatter)
313+
axs[1].xaxis.set_major_formatter('±{x}°')
313314
plt.show()
314315

315316
#############################################################################
@@ -350,27 +351,29 @@
350351

351352
##############################################################################
352353
# Finally, we can specify functions for the formatter using
353-
# `matplotlib.ticker.FuncFormatter`.
354+
# `matplotlib.ticker.FuncFormatter`. Further, like
355+
# `matplotlib.ticker.StrMethodFormatter`, simply passing a function will
356+
# automatically create a `matplotlib.ticker.FuncFormatter`.
354357

355358

356359
def formatoddticks(x, pos):
357360
"""Format odd tick positions
358361
"""
359362
if x % 2:
360-
return '%1.2f' % x
363+
return '{:1.2f}'.format(x)
361364
else:
362365
return ''
363366

364367

365368
fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
366369
ax.plot(x1, y1)
367-
formatter = matplotlib.ticker.FuncFormatter(formatoddticks)
368370
locator = matplotlib.ticker.MaxNLocator(nbins=6)
369-
ax.xaxis.set_major_formatter(formatter)
371+
ax.xaxis.set_major_formatter(formatoddticks)
370372
ax.xaxis.set_major_locator(locator)
371373

372374
plt.show()
373375

376+
374377
##############################################################################
375378
# Dateticks
376379
# ~~~~~~~~~

0 commit comments

Comments
 (0)