Skip to content

Commit 7b8a6b1

Browse files
GuessWhoSamFooTomAugspurger
authored andcommitted
VIS: Allow 'C0'-like plotting for plotting colors #15516 (#15873)
* VIS: Allow 'C0'-like plotting for plotting colors * Added case color='' and support for mpl < 2.0 * Updated prop_cycle references to be compatible with matplotlib 1.5 and 2.0 * Separated test; Used more consise regex
1 parent c4d71ce commit 7b8a6b1

File tree

3 files changed

+33
-5
lines changed

3 files changed

+33
-5
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ Other Enhancements
345345
- The ``skiprows`` argument in ``pd.read_csv()`` now accepts a callable function as a value (:issue:`10882`)
346346
- The ``nrows`` and ``chunksize`` arguments in ``pd.read_csv()`` are supported if both are passed (:issue:`6774`, :issue:`15755`)
347347
- ``pd.DataFrame.plot`` now prints a title above each subplot if ``suplots=True`` and ``title`` is a list of strings (:issue:`14753`)
348+
- ``pd.DataFrame.plot`` can pass `matplotlib 2.0 default color cycle as a single string as color parameter <http://matplotlib.org/2.0.0/users/colors.html#cn-color-selection>`__. (:issue:`15516`)
348349
- ``pd.Series.interpolate`` now supports timedelta as an index type with ``method='time'`` (:issue:`6424`)
349350
- ``Timedelta.isoformat`` method added for formatting Timedeltas as an `ISO 8601 duration`_. See the :ref:`Timedelta docs <timedeltas.isoformat>` (:issue:`15136`)
350351
- ``.select_dtypes()`` now allows the string 'datetimetz' to generically select datetimes with tz (:issue:`14910`)

pandas/tests/plotting/test_frame.py

+16
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ def test_plot(self):
141141
result = ax.get_axes() # deprecated
142142
self.assertIs(result, axes[0])
143143

144+
# GH 15516
145+
def test_mpl2_color_cycle_str(self):
146+
# test CN mpl 2.0 color cycle
147+
if self.mpl_ge_2_0_0:
148+
colors = ['C' + str(x) for x in range(10)]
149+
df = DataFrame(randn(10, 3), columns=['a', 'b', 'c'])
150+
for c in colors:
151+
_check_plot_works(df.plot, color=c)
152+
else:
153+
pytest.skip("not supported in matplotlib < 2.0.0")
154+
155+
def test_color_empty_string(self):
156+
df = DataFrame(randn(10, 2))
157+
with tm.assertRaises(ValueError):
158+
df.plot(color='')
159+
144160
def test_color_and_style_arguments(self):
145161
df = DataFrame({'x': [1, 2], 'y': [3, 4]})
146162
# passing both 'color' and 'style' arguments should be allowed

pandas/tools/plotting.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,18 @@ def _maybe_valid_colors(colors):
225225
# check whether each character can be convertable to colors
226226
maybe_color_cycle = _maybe_valid_colors(list(colors))
227227
if maybe_single_color and maybe_color_cycle and len(colors) > 1:
228-
msg = ("'{0}' can be parsed as both single color and "
229-
"color cycle. Specify each color using a list "
230-
"like ['{0}'] or {1}")
231-
raise ValueError(msg.format(colors, list(colors)))
228+
# Special case for single str 'CN' match and convert to hex
229+
# for supporting matplotlib < 2.0.0
230+
if re.match(r'\AC[0-9]\Z', colors) and _mpl_ge_2_0_0():
231+
hex_color = [c['color']
232+
for c in list(plt.rcParams['axes.prop_cycle'])]
233+
colors = [hex_color[int(colors[1])]]
234+
else:
235+
# this may no longer be required
236+
msg = ("'{0}' can be parsed as both single color and "
237+
"color cycle. Specify each color using a list "
238+
"like ['{0}'] or {1}")
239+
raise ValueError(msg.format(colors, list(colors)))
232240
elif maybe_single_color:
233241
colors = [colors]
234242
else:
@@ -237,7 +245,10 @@ def _maybe_valid_colors(colors):
237245
pass
238246

239247
if len(colors) != num_colors:
240-
multiple = num_colors // len(colors) - 1
248+
try:
249+
multiple = num_colors // len(colors) - 1
250+
except ZeroDivisionError:
251+
raise ValueError("Invalid color argument: ''")
241252
mod = num_colors % len(colors)
242253

243254
colors += multiple * colors

0 commit comments

Comments
 (0)