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

Skip to content

Commit 26ff858

Browse files
committed
ENH: New ConciseDateFormatter formatter for dates
FIX: allow non-unit aware tickers FIX: make str list length more strict DOC FIX: add kwargs to ConciseDateConverter FIX: fix cursor formatter FIX: cleanup loop logic FIX: cleanup append
1 parent d4b42b6 commit 26ff858

File tree

6 files changed

+569
-26
lines changed

6 files changed

+569
-26
lines changed

.flake8

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ per-file-ignores =
240240
examples/text_labels_and_annotations/tex_demo.py: E402
241241
examples/text_labels_and_annotations/watermark_text.py: E402
242242
examples/ticks_and_spines/auto_ticks.py: E501
243+
examples/ticks_and_spines/date_concise_formatter.py: E402
243244
examples/user_interfaces/canvasagg.py: E402
244245
examples/user_interfaces/embedding_in_gtk3_panzoom_sgskip.py: E402
245246
examples/user_interfaces/embedding_in_gtk3_sgskip.py: E402
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
:orphan:
2+
3+
New date formatter: `~.dates.ConciseDateFormatter`
4+
--------------------------------------------------
5+
6+
The automatic date formatter used by default can be quite verbose. A new
7+
formatter can be accessed that tries to make the tick labels appropriately
8+
concise.
9+
10+
.. plot::
11+
12+
import datetime
13+
import matplotlib.pyplot as plt
14+
import matplotlib.dates as mdates
15+
import numpy as np
16+
17+
# make a timeseries...
18+
base = datetime.datetime(2005, 2, 1)
19+
dates = np.array([base + datetime.timedelta(hours= 2 * i)
20+
for i in range(732)])
21+
N = len(dates)
22+
np.random.seed(19680801)
23+
y = np.cumsum(np.random.randn(N))
24+
25+
lims = [(np.datetime64('2005-02'), np.datetime64('2005-04')),
26+
(np.datetime64('2005-02-03'), np.datetime64('2005-02-15')),
27+
(np.datetime64('2005-02-03 11:00'), np.datetime64('2005-02-04 13:20'))]
28+
fig, axs = plt.subplots(3, 1, constrained_layout=True)
29+
for nn, ax in enumerate(axs):
30+
# activate the formatter here.
31+
locator = mdates.AutoDateLocator()
32+
formatter = mdates.ConciseDateFormatter(locator)
33+
ax.xaxis.set_major_locator(locator)
34+
ax.xaxis.set_major_formatter(formatter)
35+
36+
ax.plot(dates, y)
37+
ax.set_xlim(lims[nn])
38+
axs[0].set_title('Concise Date Formatter')
39+
40+
plt.show()
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
"""
2+
================================================
3+
Formatting date ticks using ConciseDateFormatter
4+
================================================
5+
6+
Finding good tick values and formatting the ticks for an axis that
7+
has date data is often a challenge. `~.dates.ConciseDateFormatter` is
8+
meant to improve the strings chosen for the ticklabels, and to minimize
9+
the strings used in those tick labels as much as possible.
10+
11+
.. note::
12+
13+
This formatter is a candidate to become the default date tick formatter
14+
in future versions of Matplotlib. Please report any issues or
15+
suggestions for improvement to the github repository or mailing list.
16+
17+
First, this is the default formatter.
18+
"""
19+
import datetime
20+
import matplotlib.pyplot as plt
21+
import matplotlib.dates as mdates
22+
import numpy as np
23+
24+
# make a timeseries...
25+
base = datetime.datetime(2005, 2, 1)
26+
dates = np.array([base + datetime.timedelta(hours=(2 * i))
27+
for i in range(732)])
28+
N = len(dates)
29+
np.random.seed(19680801)
30+
y = np.cumsum(np.random.randn(N))
31+
32+
fig, axs = plt.subplots(3, 1, constrained_layout=True, figsize=(6, 6))
33+
lims = [(np.datetime64('2005-02'), np.datetime64('2005-04')),
34+
(np.datetime64('2005-02-03'), np.datetime64('2005-02-15')),
35+
(np.datetime64('2005-02-03 11:00'), np.datetime64('2005-02-04 13:20'))]
36+
for nn, ax in enumerate(axs):
37+
ax.plot(dates, y)
38+
ax.set_xlim(lims[nn])
39+
# rotate_labels...
40+
for label in ax.get_xticklabels():
41+
label.set_rotation(40)
42+
label.set_horizontalalignment('right')
43+
axs[0].set_title('Default Date Formatter')
44+
plt.show()
45+
46+
#############################################################################
47+
# The default date formater is quite verbose, so Matplotlib has an
48+
# alternative that can be chosen with a few extra lines of code. Note,
49+
# for these axes the labels do not need to be rotated as they do for the
50+
# default formatter because the labels are as small as possible.
51+
52+
fig, axs = plt.subplots(3, 1, constrained_layout=True, figsize=(6, 6))
53+
for nn, ax in enumerate(axs):
54+
locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
55+
formatter = mdates.ConciseDateFormatter(locator)
56+
ax.xaxis.set_major_locator(locator)
57+
ax.xaxis.set_major_formatter(formatter)
58+
59+
ax.plot(dates, y)
60+
ax.set_xlim(lims[nn])
61+
axs[0].set_title('Concise Date Formatter')
62+
63+
plt.show()
64+
65+
#############################################################################
66+
# If all calls to axes that have dates are to be made using this converter,
67+
# it is probably most convenient to use the units reigistry where you do
68+
# imports:
69+
70+
import matplotlib.units as munits
71+
converter = mdates.ConciseDateConverter()
72+
munits.registry[np.datetime64] = converter
73+
munits.registry[datetime.date] = converter
74+
munits.registry[datetime.datetime] = converter
75+
76+
fig, axs = plt.subplots(3, 1, figsize=(6, 6), constrained_layout=True)
77+
for nn, ax in enumerate(axs):
78+
ax.plot(dates, y)
79+
ax.set_xlim(lims[nn])
80+
axs[0].set_title('Concise Date Formatter')
81+
82+
plt.show()
83+
84+
#############################################################################
85+
# Localization of date formats
86+
# ============================
87+
#
88+
# Dates formats can be localized if the default formats are not desirable by
89+
# manipulating one of three lists of strings.
90+
#
91+
# The ``formatter.formats`` list of formats is for the normal tick labels,
92+
# There are seven levels, years, months, days, hours, minutes, seconds, and
93+
# microseconds.
94+
# The ``formatter.offset_formats`` is how the "offset" string on the right
95+
# of the axis is formatted. This is usually much more verbose than the tick
96+
# labels. Finally, the ``formatter.zero_formats`` are the formats of the
97+
# ticks that are "zeros". These are tick values that are either the first of
98+
# the year, month, or day of month, or the zeroth hour, minute, or second.
99+
# These are usually the same as the format of
100+
# the ticks a level above. e.g. if the axis limts mean the ticks are mostly
101+
# days, then we label 1 Mar 2005 simply with a "Mar". If the axis limits
102+
# are mostly hours, we label Feb 4 00:00 as simply "Feb-4".
103+
#
104+
# Note that these format lists can also be passed to `.ConciseDateFormatter`
105+
# as optional kwargs.
106+
#
107+
# Here we modify the labels to be "day month year", instead of the ISO
108+
# "year month day":
109+
110+
fig, axs = plt.subplots(3, 1, constrained_layout=True, figsize=(6, 6))
111+
112+
for nn, ax in enumerate(axs):
113+
locator = mdates.AutoDateLocator()
114+
formatter = mdates.ConciseDateFormatter(locator)
115+
formatter.formats = ['%y', # ticks are mostly years
116+
'%b', # ticks are mostly months
117+
'%d', # ticks are mostly days
118+
'%H:%M', # hrs
119+
'%H:%M', # min
120+
'%S.%f', ] # secs
121+
# these are mostly just the level above...
122+
formatter.zero_formats = [''] + formatter.formats[:-1]
123+
# .... Except for ticks are mostly hours, its nice to have month-day
124+
formatter.zero_formats[3] = '%d-%b'
125+
126+
formatter.offset_formats = ['',
127+
'%Y',
128+
'%b %Y',
129+
'%d %b %Y',
130+
'%d %b %Y',
131+
'%d %b %Y %H:%M', ]
132+
ax.xaxis.set_major_locator(locator)
133+
ax.xaxis.set_major_formatter(formatter)
134+
135+
ax.plot(dates, y)
136+
ax.set_xlim(lims[nn])
137+
axs[0].set_title('Concise Date Formatter')
138+
139+
plt.show()
140+
141+
#############################################################################
142+
# Registering a converter with localization
143+
# =========================================
144+
#
145+
# `.ConciseDateFormatter` doesn't have rcParams entries, but localization
146+
# can be accomplished by passing kwargs to `~.ConciseDateConverter` and
147+
# registering the datatypes you will use with the units registry:
148+
149+
import datetime
150+
151+
formats = ['%y', # ticks are mostly years
152+
'%b', # ticks are mostly months
153+
'%d', # ticks are mostly days
154+
'%H:%M', # hrs
155+
'%H:%M', # min
156+
'%S.%f', ] # secs
157+
# these can be the same, except offset by one level....
158+
zero_formats = [''] + formats[:-1]
159+
# .... Except for ticks are mostly hours, its nice to have month-day
160+
zero_formats[3] = '%d-%b'
161+
offset_formats = ['',
162+
'%Y',
163+
'%b %Y',
164+
'%d %b %Y',
165+
'%d %b %Y',
166+
'%d %b %Y %H:%M', ]
167+
168+
converter = mdates.ConciseDateConverter(formats=formats,
169+
zero_formats=zero_formats,
170+
offset_formats=offset_formats)
171+
172+
munits.registry[np.datetime64] = converter
173+
munits.registry[datetime.date] = converter
174+
munits.registry[datetime.datetime] = converter
175+
176+
fig, axs = plt.subplots(3, 1, constrained_layout=True, figsize=(6, 6))
177+
for nn, ax in enumerate(axs):
178+
ax.plot(dates, y)
179+
ax.set_xlim(lims[nn])
180+
axs[0].set_title('Concise Date Formatter registered non-default')
181+
182+
plt.show()

0 commit comments

Comments
 (0)