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

Skip to content

Commit b1bdd74

Browse files
committed
Automatically create tick formatters for str and callable inputs.
1 parent 6bba974 commit b1bdd74

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
@@ -1529,37 +1529,93 @@ def set_major_formatter(self, formatter):
15291529
"""
15301530
Set the formatter of the major ticker.
15311531
1532+
In addition to a `~matplotlib.ticker.Formatter` instance,
1533+
this also accepts a `str` or function.
1534+
1535+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1536+
The field used for the value must be labeled *x* and the field used
1537+
for the position must be labeled *pos*.
1538+
1539+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1540+
The function should take in two inputs (a tick value ``x`` and a
1541+
position ``pos``), and return a string containing the corresponding
1542+
tick label.
1543+
15321544
Parameters
15331545
----------
1534-
formatter : `~matplotlib.ticker.Formatter`
1546+
formatter : `~matplotlib.ticker.Formatter`, str, or function
15351547
"""
1536-
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1537-
if (isinstance(formatter, mticker.FixedFormatter)
1538-
and len(formatter.seq) > 0
1539-
and not isinstance(self.major.locator, mticker.FixedLocator)):
1540-
cbook._warn_external('FixedFormatter should only be used together '
1541-
'with FixedLocator')
1542-
self.isDefault_majfmt = False
1543-
self.major.formatter = formatter
1544-
formatter.set_axis(self)
1545-
self.stale = True
1548+
self._set_formatter(formatter, self.major)
15461549

15471550
def set_minor_formatter(self, formatter):
15481551
"""
15491552
Set the formatter of the minor ticker.
15501553
1554+
In addition to a `~matplotlib.ticker.Formatter` instance,
1555+
this also accepts a `str` or function.
1556+
1557+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1558+
The field used for the tick value must be labeled *x* and the field
1559+
used for the tick position must be labeled *pos*.
1560+
See the `~matplotlib.ticker.StrMethodFormatter` documentation for
1561+
more information.
1562+
1563+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1564+
The function should take in two inputs (a tick value ``x`` and a
1565+
position ``pos``), and return a string containing the corresponding
1566+
tick label.
1567+
See the `~matplotlib.ticker.FuncFormatter` documentation for
1568+
more information.
1569+
15511570
Parameters
15521571
----------
1553-
formatter : `~matplotlib.ticker.Formatter`
1572+
formatter : `~matplotlib.ticker.Formatter`, str, or function
15541573
"""
1555-
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1574+
self._set_formatter(formatter, self.minor)
1575+
1576+
def _set_formatter(self, formatter, level):
1577+
"""
1578+
Set the formatter of the major or minor ticker.
1579+
1580+
In addition to a `~matplotlib.ticker.Formatter` instance,
1581+
this also accepts a `str` or function.
1582+
1583+
For a `str` a `~matplotlib.ticker.StrMethodFormatter` is used.
1584+
The field used for the value must be labeled *x* and the field used
1585+
for the position must be labeled *pos*.
1586+
1587+
For a function a `~matplotlib.ticker.FuncFormatter` is used.
1588+
The function should take in two inputs (a tick value ``x`` and a
1589+
position ``pos``), and return a string containing the corresponding
1590+
tick label.
1591+
1592+
Parameters
1593+
----------
1594+
formatter : `~matplotlib.ticker.Formatter`, str, or function
1595+
level : `self.major` or `self.minor`
1596+
"""
1597+
if isinstance(formatter, str):
1598+
formatter = mticker.StrMethodFormatter(formatter)
1599+
# Don't allow any other TickHelper to avoid easy-to-make errors,
1600+
# like using a Locator instead of a Formatter.
1601+
elif (callable(formatter) and
1602+
not isinstance(formatter, mticker.TickHelper)):
1603+
formatter = mticker.FuncFormatter(formatter)
1604+
else:
1605+
cbook._check_isinstance(mticker.Formatter, formatter=formatter)
1606+
15561607
if (isinstance(formatter, mticker.FixedFormatter)
15571608
and len(formatter.seq) > 0
1558-
and not isinstance(self.minor.locator, mticker.FixedLocator)):
1609+
and not isinstance(level.locator, mticker.FixedLocator)):
15591610
cbook._warn_external('FixedFormatter should only be used together '
15601611
'with FixedLocator')
1561-
self.isDefault_minfmt = False
1562-
self.minor.formatter = formatter
1612+
1613+
if level == self.major:
1614+
self.isDefault_majfmt = False
1615+
else:
1616+
self.isDefault_minfmt = False
1617+
1618+
level.formatter = formatter
15631619
formatter.set_axis(self)
15641620
self.stale = True
15651621

lib/matplotlib/tests/test_axes.py

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

205205

206+
def test_auto_formatter():
207+
def _formfunc(x, pos):
208+
return ''
209+
210+
formstr = '{x}_{pos}'
211+
212+
ax = plt.figure().subplots()
213+
ax.xaxis.set_major_formatter(_formfunc)
214+
ax.yaxis.set_minor_formatter(formstr)
215+
216+
targ_funcformatter = mticker.FuncFormatter(_formfunc)
217+
targ_strformatter = mticker.StrMethodFormatter(formstr)
218+
219+
assert isinstance(ax.xaxis.get_major_formatter(),
220+
mticker.FuncFormatter)
221+
assert isinstance(ax.yaxis.get_minor_formatter(),
222+
mticker.StrMethodFormatter)
223+
224+
assert ax.xaxis.get_major_formatter().func == targ_funcformatter.func
225+
assert ax.yaxis.get_minor_formatter().fmt == targ_strformatter.fmt
226+
227+
206228
@image_comparison(["twin_axis_locators_formatters"])
207229
def test_twin_axis_locators_formatters():
208230
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.
@@ -418,8 +424,8 @@ class StrMethodFormatter(Formatter):
418424
"""
419425
Use a new-style format string (as used by `str.format`) to format the tick.
420426
421-
The field used for the value must be labeled *x* and the field used
422-
for the position must be labeled *pos*.
427+
The field used for the tick value must be labeled *x* and the field used
428+
for the tick position must be labeled *pos*.
423429
"""
424430
def __init__(self, fmt):
425431
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)