test_series.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  1. # coding: utf-8
  2. """ Test cases for Series.plot """
  3. from datetime import datetime
  4. from itertools import chain
  5. import numpy as np
  6. from numpy.random import randn
  7. import pytest
  8. from pandas.compat import lrange, range
  9. import pandas.util._test_decorators as td
  10. import pandas as pd
  11. from pandas import DataFrame, Series, date_range
  12. from pandas.tests.plotting.common import (
  13. TestPlotBase, _check_plot_works, _ok_for_gaussian_kde,
  14. _skip_if_no_scipy_gaussian_kde)
  15. import pandas.util.testing as tm
  16. import pandas.plotting as plotting
  17. @td.skip_if_no_mpl
  18. class TestSeriesPlots(TestPlotBase):
  19. def setup_method(self, method):
  20. TestPlotBase.setup_method(self, method)
  21. import matplotlib as mpl
  22. mpl.rcdefaults()
  23. self.ts = tm.makeTimeSeries()
  24. self.ts.name = 'ts'
  25. self.series = tm.makeStringSeries()
  26. self.series.name = 'series'
  27. self.iseries = tm.makePeriodSeries()
  28. self.iseries.name = 'iseries'
  29. @pytest.mark.slow
  30. def test_plot(self):
  31. _check_plot_works(self.ts.plot, label='foo')
  32. _check_plot_works(self.ts.plot, use_index=False)
  33. axes = _check_plot_works(self.ts.plot, rot=0)
  34. self._check_ticks_props(axes, xrot=0)
  35. ax = _check_plot_works(self.ts.plot, style='.', logy=True)
  36. self._check_ax_scales(ax, yaxis='log')
  37. ax = _check_plot_works(self.ts.plot, style='.', logx=True)
  38. self._check_ax_scales(ax, xaxis='log')
  39. ax = _check_plot_works(self.ts.plot, style='.', loglog=True)
  40. self._check_ax_scales(ax, xaxis='log', yaxis='log')
  41. _check_plot_works(self.ts[:10].plot.bar)
  42. _check_plot_works(self.ts.plot.area, stacked=False)
  43. _check_plot_works(self.iseries.plot)
  44. for kind in ['line', 'bar', 'barh', 'kde', 'hist', 'box']:
  45. if not _ok_for_gaussian_kde(kind):
  46. continue
  47. _check_plot_works(self.series[:5].plot, kind=kind)
  48. _check_plot_works(self.series[:10].plot.barh)
  49. ax = _check_plot_works(Series(randn(10)).plot.bar, color='black')
  50. self._check_colors([ax.patches[0]], facecolors=['black'])
  51. # GH 6951
  52. ax = _check_plot_works(self.ts.plot, subplots=True)
  53. self._check_axes_shape(ax, axes_num=1, layout=(1, 1))
  54. ax = _check_plot_works(self.ts.plot, subplots=True, layout=(-1, 1))
  55. self._check_axes_shape(ax, axes_num=1, layout=(1, 1))
  56. ax = _check_plot_works(self.ts.plot, subplots=True, layout=(1, -1))
  57. self._check_axes_shape(ax, axes_num=1, layout=(1, 1))
  58. @pytest.mark.slow
  59. def test_plot_figsize_and_title(self):
  60. # figsize and title
  61. _, ax = self.plt.subplots()
  62. ax = self.series.plot(title='Test', figsize=(16, 8), ax=ax)
  63. self._check_text_labels(ax.title, 'Test')
  64. self._check_axes_shape(ax, axes_num=1, layout=(1, 1), figsize=(16, 8))
  65. def test_dont_modify_rcParams(self):
  66. # GH 8242
  67. key = 'axes.prop_cycle'
  68. colors = self.plt.rcParams[key]
  69. _, ax = self.plt.subplots()
  70. Series([1, 2, 3]).plot(ax=ax)
  71. assert colors == self.plt.rcParams[key]
  72. def test_ts_line_lim(self):
  73. fig, ax = self.plt.subplots()
  74. ax = self.ts.plot(ax=ax)
  75. xmin, xmax = ax.get_xlim()
  76. lines = ax.get_lines()
  77. assert xmin <= lines[0].get_data(orig=False)[0][0]
  78. assert xmax >= lines[0].get_data(orig=False)[0][-1]
  79. tm.close()
  80. ax = self.ts.plot(secondary_y=True, ax=ax)
  81. xmin, xmax = ax.get_xlim()
  82. lines = ax.get_lines()
  83. assert xmin <= lines[0].get_data(orig=False)[0][0]
  84. assert xmax >= lines[0].get_data(orig=False)[0][-1]
  85. def test_ts_area_lim(self):
  86. _, ax = self.plt.subplots()
  87. ax = self.ts.plot.area(stacked=False, ax=ax)
  88. xmin, xmax = ax.get_xlim()
  89. line = ax.get_lines()[0].get_data(orig=False)[0]
  90. assert xmin <= line[0]
  91. assert xmax >= line[-1]
  92. tm.close()
  93. # GH 7471
  94. _, ax = self.plt.subplots()
  95. ax = self.ts.plot.area(stacked=False, x_compat=True, ax=ax)
  96. xmin, xmax = ax.get_xlim()
  97. line = ax.get_lines()[0].get_data(orig=False)[0]
  98. assert xmin <= line[0]
  99. assert xmax >= line[-1]
  100. tm.close()
  101. tz_ts = self.ts.copy()
  102. tz_ts.index = tz_ts.tz_localize('GMT').tz_convert('CET')
  103. _, ax = self.plt.subplots()
  104. ax = tz_ts.plot.area(stacked=False, x_compat=True, ax=ax)
  105. xmin, xmax = ax.get_xlim()
  106. line = ax.get_lines()[0].get_data(orig=False)[0]
  107. assert xmin <= line[0]
  108. assert xmax >= line[-1]
  109. tm.close()
  110. _, ax = self.plt.subplots()
  111. ax = tz_ts.plot.area(stacked=False, secondary_y=True, ax=ax)
  112. xmin, xmax = ax.get_xlim()
  113. line = ax.get_lines()[0].get_data(orig=False)[0]
  114. assert xmin <= line[0]
  115. assert xmax >= line[-1]
  116. def test_label(self):
  117. s = Series([1, 2])
  118. _, ax = self.plt.subplots()
  119. ax = s.plot(label='LABEL', legend=True, ax=ax)
  120. self._check_legend_labels(ax, labels=['LABEL'])
  121. self.plt.close()
  122. _, ax = self.plt.subplots()
  123. ax = s.plot(legend=True, ax=ax)
  124. self._check_legend_labels(ax, labels=['None'])
  125. self.plt.close()
  126. # get name from index
  127. s.name = 'NAME'
  128. _, ax = self.plt.subplots()
  129. ax = s.plot(legend=True, ax=ax)
  130. self._check_legend_labels(ax, labels=['NAME'])
  131. self.plt.close()
  132. # override the default
  133. _, ax = self.plt.subplots()
  134. ax = s.plot(legend=True, label='LABEL', ax=ax)
  135. self._check_legend_labels(ax, labels=['LABEL'])
  136. self.plt.close()
  137. # Add lebel info, but don't draw
  138. _, ax = self.plt.subplots()
  139. ax = s.plot(legend=False, label='LABEL', ax=ax)
  140. assert ax.get_legend() is None # Hasn't been drawn
  141. ax.legend() # draw it
  142. self._check_legend_labels(ax, labels=['LABEL'])
  143. def test_line_area_nan_series(self):
  144. values = [1, 2, np.nan, 3]
  145. s = Series(values)
  146. ts = Series(values, index=tm.makeDateIndex(k=4))
  147. for d in [s, ts]:
  148. ax = _check_plot_works(d.plot)
  149. masked = ax.lines[0].get_ydata()
  150. # remove nan for comparison purpose
  151. exp = np.array([1, 2, 3], dtype=np.float64)
  152. tm.assert_numpy_array_equal(np.delete(masked.data, 2), exp)
  153. tm.assert_numpy_array_equal(
  154. masked.mask, np.array([False, False, True, False]))
  155. expected = np.array([1, 2, 0, 3], dtype=np.float64)
  156. ax = _check_plot_works(d.plot, stacked=True)
  157. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected)
  158. ax = _check_plot_works(d.plot.area)
  159. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected)
  160. ax = _check_plot_works(d.plot.area, stacked=False)
  161. tm.assert_numpy_array_equal(ax.lines[0].get_ydata(), expected)
  162. def test_line_use_index_false(self):
  163. s = Series([1, 2, 3], index=['a', 'b', 'c'])
  164. s.index.name = 'The Index'
  165. _, ax = self.plt.subplots()
  166. ax = s.plot(use_index=False, ax=ax)
  167. label = ax.get_xlabel()
  168. assert label == ''
  169. _, ax = self.plt.subplots()
  170. ax2 = s.plot.bar(use_index=False, ax=ax)
  171. label2 = ax2.get_xlabel()
  172. assert label2 == ''
  173. @pytest.mark.slow
  174. def test_bar_log(self):
  175. expected = np.array([1e-1, 1e0, 1e1, 1e2, 1e3, 1e4])
  176. _, ax = self.plt.subplots()
  177. ax = Series([200, 500]).plot.bar(log=True, ax=ax)
  178. tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), expected)
  179. tm.close()
  180. _, ax = self.plt.subplots()
  181. ax = Series([200, 500]).plot.barh(log=True, ax=ax)
  182. tm.assert_numpy_array_equal(ax.xaxis.get_ticklocs(), expected)
  183. tm.close()
  184. # GH 9905
  185. expected = np.array([1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e0, 1e1])
  186. _, ax = self.plt.subplots()
  187. ax = Series([0.1, 0.01, 0.001]).plot(log=True, kind='bar', ax=ax)
  188. ymin = 0.0007943282347242822
  189. ymax = 0.12589254117941673
  190. res = ax.get_ylim()
  191. tm.assert_almost_equal(res[0], ymin)
  192. tm.assert_almost_equal(res[1], ymax)
  193. tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), expected)
  194. tm.close()
  195. _, ax = self.plt.subplots()
  196. ax = Series([0.1, 0.01, 0.001]).plot(log=True, kind='barh', ax=ax)
  197. res = ax.get_xlim()
  198. tm.assert_almost_equal(res[0], ymin)
  199. tm.assert_almost_equal(res[1], ymax)
  200. tm.assert_numpy_array_equal(ax.xaxis.get_ticklocs(), expected)
  201. @pytest.mark.slow
  202. def test_bar_ignore_index(self):
  203. df = Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
  204. _, ax = self.plt.subplots()
  205. ax = df.plot.bar(use_index=False, ax=ax)
  206. self._check_text_labels(ax.get_xticklabels(), ['0', '1', '2', '3'])
  207. def test_bar_user_colors(self):
  208. s = Series([1, 2, 3, 4])
  209. ax = s.plot.bar(color=['red', 'blue', 'blue', 'red'])
  210. result = [p.get_facecolor() for p in ax.patches]
  211. expected = [(1., 0., 0., 1.),
  212. (0., 0., 1., 1.),
  213. (0., 0., 1., 1.),
  214. (1., 0., 0., 1.)]
  215. assert result == expected
  216. def test_rotation(self):
  217. df = DataFrame(randn(5, 5))
  218. # Default rot 0
  219. _, ax = self.plt.subplots()
  220. axes = df.plot(ax=ax)
  221. self._check_ticks_props(axes, xrot=0)
  222. _, ax = self.plt.subplots()
  223. axes = df.plot(rot=30, ax=ax)
  224. self._check_ticks_props(axes, xrot=30)
  225. def test_irregular_datetime(self):
  226. rng = date_range('1/1/2000', '3/1/2000')
  227. rng = rng[[0, 1, 2, 3, 5, 9, 10, 11, 12]]
  228. ser = Series(randn(len(rng)), rng)
  229. _, ax = self.plt.subplots()
  230. ax = ser.plot(ax=ax)
  231. xp = datetime(1999, 1, 1).toordinal()
  232. ax.set_xlim('1/1/1999', '1/1/2001')
  233. assert xp == ax.get_xlim()[0]
  234. def test_unsorted_index_xlim(self):
  235. ser = Series([0., 1., np.nan, 3., 4., 5., 6.],
  236. index=[1., 0., 3., 2., np.nan, 3., 2.])
  237. _, ax = self.plt.subplots()
  238. ax = ser.plot(ax=ax)
  239. xmin, xmax = ax.get_xlim()
  240. lines = ax.get_lines()
  241. assert xmin <= np.nanmin(lines[0].get_data(orig=False)[0])
  242. assert xmax >= np.nanmax(lines[0].get_data(orig=False)[0])
  243. @pytest.mark.slow
  244. def test_pie_series(self):
  245. # if sum of values is less than 1.0, pie handle them as rate and draw
  246. # semicircle.
  247. series = Series(np.random.randint(1, 5),
  248. index=['a', 'b', 'c', 'd', 'e'], name='YLABEL')
  249. ax = _check_plot_works(series.plot.pie)
  250. self._check_text_labels(ax.texts, series.index)
  251. assert ax.get_ylabel() == 'YLABEL'
  252. # without wedge labels
  253. ax = _check_plot_works(series.plot.pie, labels=None)
  254. self._check_text_labels(ax.texts, [''] * 5)
  255. # with less colors than elements
  256. color_args = ['r', 'g', 'b']
  257. ax = _check_plot_works(series.plot.pie, colors=color_args)
  258. color_expected = ['r', 'g', 'b', 'r', 'g']
  259. self._check_colors(ax.patches, facecolors=color_expected)
  260. # with labels and colors
  261. labels = ['A', 'B', 'C', 'D', 'E']
  262. color_args = ['r', 'g', 'b', 'c', 'm']
  263. ax = _check_plot_works(series.plot.pie, labels=labels,
  264. colors=color_args)
  265. self._check_text_labels(ax.texts, labels)
  266. self._check_colors(ax.patches, facecolors=color_args)
  267. # with autopct and fontsize
  268. ax = _check_plot_works(series.plot.pie, colors=color_args,
  269. autopct='%.2f', fontsize=7)
  270. pcts = ['{0:.2f}'.format(s * 100)
  271. for s in series.values / float(series.sum())]
  272. expected_texts = list(chain.from_iterable(zip(series.index, pcts)))
  273. self._check_text_labels(ax.texts, expected_texts)
  274. for t in ax.texts:
  275. assert t.get_fontsize() == 7
  276. # includes negative value
  277. with pytest.raises(ValueError):
  278. series = Series([1, 2, 0, 4, -1], index=['a', 'b', 'c', 'd', 'e'])
  279. series.plot.pie()
  280. # includes nan
  281. series = Series([1, 2, np.nan, 4], index=['a', 'b', 'c', 'd'],
  282. name='YLABEL')
  283. ax = _check_plot_works(series.plot.pie)
  284. self._check_text_labels(ax.texts, ['a', 'b', '', 'd'])
  285. def test_pie_nan(self):
  286. s = Series([1, np.nan, 1, 1])
  287. _, ax = self.plt.subplots()
  288. ax = s.plot.pie(legend=True, ax=ax)
  289. expected = ['0', '', '2', '3']
  290. result = [x.get_text() for x in ax.texts]
  291. assert result == expected
  292. @pytest.mark.slow
  293. def test_hist_df_kwargs(self):
  294. df = DataFrame(np.random.randn(10, 2))
  295. _, ax = self.plt.subplots()
  296. ax = df.plot.hist(bins=5, ax=ax)
  297. assert len(ax.patches) == 10
  298. @pytest.mark.slow
  299. def test_hist_df_with_nonnumerics(self):
  300. # GH 9853
  301. with tm.RNGContext(1):
  302. df = DataFrame(
  303. np.random.randn(10, 4), columns=['A', 'B', 'C', 'D'])
  304. df['E'] = ['x', 'y'] * 5
  305. _, ax = self.plt.subplots()
  306. ax = df.plot.hist(bins=5, ax=ax)
  307. assert len(ax.patches) == 20
  308. _, ax = self.plt.subplots()
  309. ax = df.plot.hist(ax=ax) # bins=10
  310. assert len(ax.patches) == 40
  311. @pytest.mark.slow
  312. def test_hist_legacy(self):
  313. _check_plot_works(self.ts.hist)
  314. _check_plot_works(self.ts.hist, grid=False)
  315. _check_plot_works(self.ts.hist, figsize=(8, 10))
  316. # _check_plot_works adds an ax so catch warning. see GH #13188
  317. with tm.assert_produces_warning(UserWarning):
  318. _check_plot_works(self.ts.hist,
  319. by=self.ts.index.month)
  320. with tm.assert_produces_warning(UserWarning):
  321. _check_plot_works(self.ts.hist,
  322. by=self.ts.index.month, bins=5)
  323. fig, ax = self.plt.subplots(1, 1)
  324. _check_plot_works(self.ts.hist, ax=ax)
  325. _check_plot_works(self.ts.hist, ax=ax, figure=fig)
  326. _check_plot_works(self.ts.hist, figure=fig)
  327. tm.close()
  328. fig, (ax1, ax2) = self.plt.subplots(1, 2)
  329. _check_plot_works(self.ts.hist, figure=fig, ax=ax1)
  330. _check_plot_works(self.ts.hist, figure=fig, ax=ax2)
  331. with pytest.raises(ValueError):
  332. self.ts.hist(by=self.ts.index, figure=fig)
  333. @pytest.mark.slow
  334. def test_hist_bins_legacy(self):
  335. df = DataFrame(np.random.randn(10, 2))
  336. ax = df.hist(bins=2)[0][0]
  337. assert len(ax.patches) == 2
  338. @pytest.mark.slow
  339. def test_hist_layout(self):
  340. df = self.hist_df
  341. with pytest.raises(ValueError):
  342. df.height.hist(layout=(1, 1))
  343. with pytest.raises(ValueError):
  344. df.height.hist(layout=[1, 1])
  345. @pytest.mark.slow
  346. def test_hist_layout_with_by(self):
  347. df = self.hist_df
  348. # _check_plot_works adds an ax so catch warning. see GH #13188
  349. with tm.assert_produces_warning(UserWarning):
  350. axes = _check_plot_works(df.height.hist,
  351. by=df.gender, layout=(2, 1))
  352. self._check_axes_shape(axes, axes_num=2, layout=(2, 1))
  353. with tm.assert_produces_warning(UserWarning):
  354. axes = _check_plot_works(df.height.hist,
  355. by=df.gender, layout=(3, -1))
  356. self._check_axes_shape(axes, axes_num=2, layout=(3, 1))
  357. with tm.assert_produces_warning(UserWarning):
  358. axes = _check_plot_works(df.height.hist,
  359. by=df.category, layout=(4, 1))
  360. self._check_axes_shape(axes, axes_num=4, layout=(4, 1))
  361. with tm.assert_produces_warning(UserWarning):
  362. axes = _check_plot_works(df.height.hist,
  363. by=df.category, layout=(2, -1))
  364. self._check_axes_shape(axes, axes_num=4, layout=(2, 2))
  365. with tm.assert_produces_warning(UserWarning):
  366. axes = _check_plot_works(df.height.hist,
  367. by=df.category, layout=(3, -1))
  368. self._check_axes_shape(axes, axes_num=4, layout=(3, 2))
  369. with tm.assert_produces_warning(UserWarning):
  370. axes = _check_plot_works(df.height.hist,
  371. by=df.category, layout=(-1, 4))
  372. self._check_axes_shape(axes, axes_num=4, layout=(1, 4))
  373. with tm.assert_produces_warning(UserWarning):
  374. axes = _check_plot_works(df.height.hist,
  375. by=df.classroom, layout=(2, 2))
  376. self._check_axes_shape(axes, axes_num=3, layout=(2, 2))
  377. axes = df.height.hist(by=df.category, layout=(4, 2), figsize=(12, 7))
  378. self._check_axes_shape(axes, axes_num=4, layout=(4, 2),
  379. figsize=(12, 7))
  380. @pytest.mark.slow
  381. def test_hist_no_overlap(self):
  382. from matplotlib.pyplot import subplot, gcf
  383. x = Series(randn(2))
  384. y = Series(randn(2))
  385. subplot(121)
  386. x.hist()
  387. subplot(122)
  388. y.hist()
  389. fig = gcf()
  390. axes = fig.axes
  391. assert len(axes) == 2
  392. @pytest.mark.slow
  393. def test_hist_secondary_legend(self):
  394. # GH 9610
  395. df = DataFrame(np.random.randn(30, 4), columns=list('abcd'))
  396. # primary -> secondary
  397. _, ax = self.plt.subplots()
  398. ax = df['a'].plot.hist(legend=True, ax=ax)
  399. df['b'].plot.hist(ax=ax, legend=True, secondary_y=True)
  400. # both legends are dran on left ax
  401. # left and right axis must be visible
  402. self._check_legend_labels(ax, labels=['a', 'b (right)'])
  403. assert ax.get_yaxis().get_visible()
  404. assert ax.right_ax.get_yaxis().get_visible()
  405. tm.close()
  406. # secondary -> secondary
  407. _, ax = self.plt.subplots()
  408. ax = df['a'].plot.hist(legend=True, secondary_y=True, ax=ax)
  409. df['b'].plot.hist(ax=ax, legend=True, secondary_y=True)
  410. # both legends are draw on left ax
  411. # left axis must be invisible, right axis must be visible
  412. self._check_legend_labels(ax.left_ax,
  413. labels=['a (right)', 'b (right)'])
  414. assert not ax.left_ax.get_yaxis().get_visible()
  415. assert ax.get_yaxis().get_visible()
  416. tm.close()
  417. # secondary -> primary
  418. _, ax = self.plt.subplots()
  419. ax = df['a'].plot.hist(legend=True, secondary_y=True, ax=ax)
  420. # right axes is returned
  421. df['b'].plot.hist(ax=ax, legend=True)
  422. # both legends are draw on left ax
  423. # left and right axis must be visible
  424. self._check_legend_labels(ax.left_ax, labels=['a (right)', 'b'])
  425. assert ax.left_ax.get_yaxis().get_visible()
  426. assert ax.get_yaxis().get_visible()
  427. tm.close()
  428. @pytest.mark.slow
  429. def test_df_series_secondary_legend(self):
  430. # GH 9779
  431. df = DataFrame(np.random.randn(30, 3), columns=list('abc'))
  432. s = Series(np.random.randn(30), name='x')
  433. # primary -> secondary (without passing ax)
  434. _, ax = self.plt.subplots()
  435. ax = df.plot(ax=ax)
  436. s.plot(legend=True, secondary_y=True, ax=ax)
  437. # both legends are dran on left ax
  438. # left and right axis must be visible
  439. self._check_legend_labels(ax, labels=['a', 'b', 'c', 'x (right)'])
  440. assert ax.get_yaxis().get_visible()
  441. assert ax.right_ax.get_yaxis().get_visible()
  442. tm.close()
  443. # primary -> secondary (with passing ax)
  444. _, ax = self.plt.subplots()
  445. ax = df.plot(ax=ax)
  446. s.plot(ax=ax, legend=True, secondary_y=True)
  447. # both legends are dran on left ax
  448. # left and right axis must be visible
  449. self._check_legend_labels(ax, labels=['a', 'b', 'c', 'x (right)'])
  450. assert ax.get_yaxis().get_visible()
  451. assert ax.right_ax.get_yaxis().get_visible()
  452. tm.close()
  453. # seconcary -> secondary (without passing ax)
  454. _, ax = self.plt.subplots()
  455. ax = df.plot(secondary_y=True, ax=ax)
  456. s.plot(legend=True, secondary_y=True, ax=ax)
  457. # both legends are dran on left ax
  458. # left axis must be invisible and right axis must be visible
  459. expected = ['a (right)', 'b (right)', 'c (right)', 'x (right)']
  460. self._check_legend_labels(ax.left_ax, labels=expected)
  461. assert not ax.left_ax.get_yaxis().get_visible()
  462. assert ax.get_yaxis().get_visible()
  463. tm.close()
  464. # secondary -> secondary (with passing ax)
  465. _, ax = self.plt.subplots()
  466. ax = df.plot(secondary_y=True, ax=ax)
  467. s.plot(ax=ax, legend=True, secondary_y=True)
  468. # both legends are dran on left ax
  469. # left axis must be invisible and right axis must be visible
  470. expected = ['a (right)', 'b (right)', 'c (right)', 'x (right)']
  471. self._check_legend_labels(ax.left_ax, expected)
  472. assert not ax.left_ax.get_yaxis().get_visible()
  473. assert ax.get_yaxis().get_visible()
  474. tm.close()
  475. # secondary -> secondary (with passing ax)
  476. _, ax = self.plt.subplots()
  477. ax = df.plot(secondary_y=True, mark_right=False, ax=ax)
  478. s.plot(ax=ax, legend=True, secondary_y=True)
  479. # both legends are dran on left ax
  480. # left axis must be invisible and right axis must be visible
  481. expected = ['a', 'b', 'c', 'x (right)']
  482. self._check_legend_labels(ax.left_ax, expected)
  483. assert not ax.left_ax.get_yaxis().get_visible()
  484. assert ax.get_yaxis().get_visible()
  485. tm.close()
  486. @pytest.mark.slow
  487. def test_secondary_logy(self):
  488. # GH 25545
  489. s1 = Series(np.random.randn(30))
  490. s2 = Series(np.random.randn(30))
  491. ax1 = s1.plot(logy=True)
  492. ax2 = s2.plot(secondary_y=True, logy=True)
  493. assert ax1.get_yscale() == 'log'
  494. assert ax2.get_yscale() == 'log'
  495. @pytest.mark.slow
  496. def test_plot_fails_with_dupe_color_and_style(self):
  497. x = Series(randn(2))
  498. with pytest.raises(ValueError):
  499. _, ax = self.plt.subplots()
  500. x.plot(style='k--', color='k', ax=ax)
  501. @pytest.mark.slow
  502. @td.skip_if_no_scipy
  503. def test_hist_kde(self):
  504. _, ax = self.plt.subplots()
  505. ax = self.ts.plot.hist(logy=True, ax=ax)
  506. self._check_ax_scales(ax, yaxis='log')
  507. xlabels = ax.get_xticklabels()
  508. # ticks are values, thus ticklabels are blank
  509. self._check_text_labels(xlabels, [''] * len(xlabels))
  510. ylabels = ax.get_yticklabels()
  511. self._check_text_labels(ylabels, [''] * len(ylabels))
  512. _skip_if_no_scipy_gaussian_kde()
  513. _check_plot_works(self.ts.plot.kde)
  514. _check_plot_works(self.ts.plot.density)
  515. _, ax = self.plt.subplots()
  516. ax = self.ts.plot.kde(logy=True, ax=ax)
  517. self._check_ax_scales(ax, yaxis='log')
  518. xlabels = ax.get_xticklabels()
  519. self._check_text_labels(xlabels, [''] * len(xlabels))
  520. ylabels = ax.get_yticklabels()
  521. self._check_text_labels(ylabels, [''] * len(ylabels))
  522. @pytest.mark.slow
  523. @td.skip_if_no_scipy
  524. def test_kde_kwargs(self):
  525. _skip_if_no_scipy_gaussian_kde()
  526. sample_points = np.linspace(-100, 100, 20)
  527. _check_plot_works(self.ts.plot.kde, bw_method='scott', ind=20)
  528. _check_plot_works(self.ts.plot.kde, bw_method=None, ind=20)
  529. _check_plot_works(self.ts.plot.kde, bw_method=None, ind=np.int(20))
  530. _check_plot_works(self.ts.plot.kde, bw_method=.5, ind=sample_points)
  531. _check_plot_works(self.ts.plot.density, bw_method=.5,
  532. ind=sample_points)
  533. _, ax = self.plt.subplots()
  534. ax = self.ts.plot.kde(logy=True, bw_method=.5, ind=sample_points,
  535. ax=ax)
  536. self._check_ax_scales(ax, yaxis='log')
  537. self._check_text_labels(ax.yaxis.get_label(), 'Density')
  538. @pytest.mark.slow
  539. @td.skip_if_no_scipy
  540. def test_kde_missing_vals(self):
  541. _skip_if_no_scipy_gaussian_kde()
  542. s = Series(np.random.uniform(size=50))
  543. s[0] = np.nan
  544. axes = _check_plot_works(s.plot.kde)
  545. # gh-14821: check if the values have any missing values
  546. assert any(~np.isnan(axes.lines[0].get_xdata()))
  547. @pytest.mark.slow
  548. def test_hist_kwargs(self):
  549. _, ax = self.plt.subplots()
  550. ax = self.ts.plot.hist(bins=5, ax=ax)
  551. assert len(ax.patches) == 5
  552. self._check_text_labels(ax.yaxis.get_label(), 'Frequency')
  553. tm.close()
  554. _, ax = self.plt.subplots()
  555. ax = self.ts.plot.hist(orientation='horizontal', ax=ax)
  556. self._check_text_labels(ax.xaxis.get_label(), 'Frequency')
  557. tm.close()
  558. _, ax = self.plt.subplots()
  559. ax = self.ts.plot.hist(align='left', stacked=True, ax=ax)
  560. tm.close()
  561. @pytest.mark.slow
  562. @td.skip_if_no_scipy
  563. def test_hist_kde_color(self):
  564. _, ax = self.plt.subplots()
  565. ax = self.ts.plot.hist(logy=True, bins=10, color='b', ax=ax)
  566. self._check_ax_scales(ax, yaxis='log')
  567. assert len(ax.patches) == 10
  568. self._check_colors(ax.patches, facecolors=['b'] * 10)
  569. _skip_if_no_scipy_gaussian_kde()
  570. _, ax = self.plt.subplots()
  571. ax = self.ts.plot.kde(logy=True, color='r', ax=ax)
  572. self._check_ax_scales(ax, yaxis='log')
  573. lines = ax.get_lines()
  574. assert len(lines) == 1
  575. self._check_colors(lines, ['r'])
  576. @pytest.mark.slow
  577. def test_boxplot_series(self):
  578. _, ax = self.plt.subplots()
  579. ax = self.ts.plot.box(logy=True, ax=ax)
  580. self._check_ax_scales(ax, yaxis='log')
  581. xlabels = ax.get_xticklabels()
  582. self._check_text_labels(xlabels, [self.ts.name])
  583. ylabels = ax.get_yticklabels()
  584. self._check_text_labels(ylabels, [''] * len(ylabels))
  585. @pytest.mark.slow
  586. def test_kind_both_ways(self):
  587. s = Series(range(3))
  588. kinds = (plotting._core._common_kinds +
  589. plotting._core._series_kinds)
  590. _, ax = self.plt.subplots()
  591. for kind in kinds:
  592. if not _ok_for_gaussian_kde(kind):
  593. continue
  594. s.plot(kind=kind, ax=ax)
  595. getattr(s.plot, kind)()
  596. @pytest.mark.slow
  597. def test_invalid_plot_data(self):
  598. s = Series(list('abcd'))
  599. _, ax = self.plt.subplots()
  600. for kind in plotting._core._common_kinds:
  601. if not _ok_for_gaussian_kde(kind):
  602. continue
  603. with pytest.raises(TypeError):
  604. s.plot(kind=kind, ax=ax)
  605. @pytest.mark.slow
  606. def test_valid_object_plot(self):
  607. s = Series(lrange(10), dtype=object)
  608. for kind in plotting._core._common_kinds:
  609. if not _ok_for_gaussian_kde(kind):
  610. continue
  611. _check_plot_works(s.plot, kind=kind)
  612. def test_partially_invalid_plot_data(self):
  613. s = Series(['a', 'b', 1.0, 2])
  614. _, ax = self.plt.subplots()
  615. for kind in plotting._core._common_kinds:
  616. if not _ok_for_gaussian_kde(kind):
  617. continue
  618. with pytest.raises(TypeError):
  619. s.plot(kind=kind, ax=ax)
  620. def test_invalid_kind(self):
  621. s = Series([1, 2])
  622. with pytest.raises(ValueError):
  623. s.plot(kind='aasdf')
  624. @pytest.mark.slow
  625. def test_dup_datetime_index_plot(self):
  626. dr1 = date_range('1/1/2009', periods=4)
  627. dr2 = date_range('1/2/2009', periods=4)
  628. index = dr1.append(dr2)
  629. values = randn(index.size)
  630. s = Series(values, index=index)
  631. _check_plot_works(s.plot)
  632. @pytest.mark.slow
  633. def test_errorbar_plot(self):
  634. s = Series(np.arange(10), name='x')
  635. s_err = np.random.randn(10)
  636. d_err = DataFrame(randn(10, 2), index=s.index, columns=['x', 'y'])
  637. # test line and bar plots
  638. kinds = ['line', 'bar']
  639. for kind in kinds:
  640. ax = _check_plot_works(s.plot, yerr=Series(s_err), kind=kind)
  641. self._check_has_errorbars(ax, xerr=0, yerr=1)
  642. ax = _check_plot_works(s.plot, yerr=s_err, kind=kind)
  643. self._check_has_errorbars(ax, xerr=0, yerr=1)
  644. ax = _check_plot_works(s.plot, yerr=s_err.tolist(), kind=kind)
  645. self._check_has_errorbars(ax, xerr=0, yerr=1)
  646. ax = _check_plot_works(s.plot, yerr=d_err, kind=kind)
  647. self._check_has_errorbars(ax, xerr=0, yerr=1)
  648. ax = _check_plot_works(s.plot, xerr=0.2, yerr=0.2, kind=kind)
  649. self._check_has_errorbars(ax, xerr=1, yerr=1)
  650. ax = _check_plot_works(s.plot, xerr=s_err)
  651. self._check_has_errorbars(ax, xerr=1, yerr=0)
  652. # test time series plotting
  653. ix = date_range('1/1/2000', '1/1/2001', freq='M')
  654. ts = Series(np.arange(12), index=ix, name='x')
  655. ts_err = Series(np.random.randn(12), index=ix)
  656. td_err = DataFrame(randn(12, 2), index=ix, columns=['x', 'y'])
  657. ax = _check_plot_works(ts.plot, yerr=ts_err)
  658. self._check_has_errorbars(ax, xerr=0, yerr=1)
  659. ax = _check_plot_works(ts.plot, yerr=td_err)
  660. self._check_has_errorbars(ax, xerr=0, yerr=1)
  661. # check incorrect lengths and types
  662. with pytest.raises(ValueError):
  663. s.plot(yerr=np.arange(11))
  664. s_err = ['zzz'] * 10
  665. # MPL > 2.0.0 will most likely use TypeError here
  666. with pytest.raises((TypeError, ValueError)):
  667. s.plot(yerr=s_err)
  668. # This XPASSES when tested with mpl == 3.0.1
  669. @td.xfail_if_mpl_2_2
  670. def test_table(self):
  671. _check_plot_works(self.series.plot, table=True)
  672. _check_plot_works(self.series.plot, table=self.series)
  673. @pytest.mark.slow
  674. def test_series_grid_settings(self):
  675. # Make sure plot defaults to rcParams['axes.grid'] setting, GH 9792
  676. self._check_grid_settings(Series([1, 2, 3]),
  677. plotting._core._series_kinds +
  678. plotting._core._common_kinds)
  679. @pytest.mark.slow
  680. def test_standard_colors(self):
  681. from pandas.plotting._style import _get_standard_colors
  682. for c in ['r', 'red', 'green', '#FF0000']:
  683. result = _get_standard_colors(1, color=c)
  684. assert result == [c]
  685. result = _get_standard_colors(1, color=[c])
  686. assert result == [c]
  687. result = _get_standard_colors(3, color=c)
  688. assert result == [c] * 3
  689. result = _get_standard_colors(3, color=[c])
  690. assert result == [c] * 3
  691. @pytest.mark.slow
  692. def test_standard_colors_all(self):
  693. import matplotlib.colors as colors
  694. from pandas.plotting._style import _get_standard_colors
  695. # multiple colors like mediumaquamarine
  696. for c in colors.cnames:
  697. result = _get_standard_colors(num_colors=1, color=c)
  698. assert result == [c]
  699. result = _get_standard_colors(num_colors=1, color=[c])
  700. assert result == [c]
  701. result = _get_standard_colors(num_colors=3, color=c)
  702. assert result == [c] * 3
  703. result = _get_standard_colors(num_colors=3, color=[c])
  704. assert result == [c] * 3
  705. # single letter colors like k
  706. for c in colors.ColorConverter.colors:
  707. result = _get_standard_colors(num_colors=1, color=c)
  708. assert result == [c]
  709. result = _get_standard_colors(num_colors=1, color=[c])
  710. assert result == [c]
  711. result = _get_standard_colors(num_colors=3, color=c)
  712. assert result == [c] * 3
  713. result = _get_standard_colors(num_colors=3, color=[c])
  714. assert result == [c] * 3
  715. def test_series_plot_color_kwargs(self):
  716. # GH1890
  717. _, ax = self.plt.subplots()
  718. ax = Series(np.arange(12) + 1).plot(color='green', ax=ax)
  719. self._check_colors(ax.get_lines(), linecolors=['green'])
  720. def test_time_series_plot_color_kwargs(self):
  721. # #1890
  722. _, ax = self.plt.subplots()
  723. ax = Series(np.arange(12) + 1, index=date_range(
  724. '1/1/2000', periods=12)).plot(color='green', ax=ax)
  725. self._check_colors(ax.get_lines(), linecolors=['green'])
  726. def test_time_series_plot_color_with_empty_kwargs(self):
  727. import matplotlib as mpl
  728. def_colors = self._unpack_cycler(mpl.rcParams)
  729. index = date_range('1/1/2000', periods=12)
  730. s = Series(np.arange(1, 13), index=index)
  731. ncolors = 3
  732. _, ax = self.plt.subplots()
  733. for i in range(ncolors):
  734. ax = s.plot(ax=ax)
  735. self._check_colors(ax.get_lines(), linecolors=def_colors[:ncolors])
  736. def test_xticklabels(self):
  737. # GH11529
  738. s = Series(np.arange(10), index=['P%02d' % i for i in range(10)])
  739. _, ax = self.plt.subplots()
  740. ax = s.plot(xticks=[0, 3, 5, 9], ax=ax)
  741. exp = ['P%02d' % i for i in [0, 3, 5, 9]]
  742. self._check_text_labels(ax.get_xticklabels(), exp)
  743. def test_custom_business_day_freq(self):
  744. # GH7222
  745. from pandas.tseries.offsets import CustomBusinessDay
  746. s = Series(range(100, 121), index=pd.bdate_range(
  747. start='2014-05-01', end='2014-06-01',
  748. freq=CustomBusinessDay(holidays=['2014-05-26'])))
  749. _check_plot_works(s.plot)
  750. @pytest.mark.xfail
  751. def test_plot_accessor_updates_on_inplace(self):
  752. s = Series([1, 2, 3, 4])
  753. _, ax = self.plt.subplots()
  754. ax = s.plot(ax=ax)
  755. before = ax.xaxis.get_ticklocs()
  756. s.drop([0, 1], inplace=True)
  757. _, ax = self.plt.subplots()
  758. after = ax.xaxis.get_ticklocs()
  759. tm.assert_numpy_array_equal(before, after)