test_misc.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. # coding: utf-8
  2. """ Test cases for misc plot functions """
  3. import numpy as np
  4. from numpy import random
  5. from numpy.random import randn
  6. import pytest
  7. from pandas.compat import lmap
  8. import pandas.util._test_decorators as td
  9. from pandas import DataFrame
  10. from pandas.tests.plotting.common import TestPlotBase, _check_plot_works
  11. import pandas.util.testing as tm
  12. import pandas.plotting as plotting
  13. @td.skip_if_mpl
  14. def test_import_error_message():
  15. # GH-19810
  16. df = DataFrame({"A": [1, 2]})
  17. with pytest.raises(ImportError, match='matplotlib is required'):
  18. df.plot()
  19. @td.skip_if_no_mpl
  20. class TestSeriesPlots(TestPlotBase):
  21. def setup_method(self, method):
  22. TestPlotBase.setup_method(self, method)
  23. import matplotlib as mpl
  24. mpl.rcdefaults()
  25. self.ts = tm.makeTimeSeries()
  26. self.ts.name = 'ts'
  27. @pytest.mark.slow
  28. def test_autocorrelation_plot(self):
  29. from pandas.plotting import autocorrelation_plot
  30. _check_plot_works(autocorrelation_plot, series=self.ts)
  31. _check_plot_works(autocorrelation_plot, series=self.ts.values)
  32. ax = autocorrelation_plot(self.ts, label='Test')
  33. self._check_legend_labels(ax, labels=['Test'])
  34. @pytest.mark.slow
  35. def test_lag_plot(self):
  36. from pandas.plotting import lag_plot
  37. _check_plot_works(lag_plot, series=self.ts)
  38. _check_plot_works(lag_plot, series=self.ts, lag=5)
  39. @pytest.mark.slow
  40. def test_bootstrap_plot(self):
  41. from pandas.plotting import bootstrap_plot
  42. _check_plot_works(bootstrap_plot, series=self.ts, size=10)
  43. @td.skip_if_no_mpl
  44. class TestDataFramePlots(TestPlotBase):
  45. # This XPASSES when tested with mpl == 3.0.1
  46. @td.xfail_if_mpl_2_2
  47. @td.skip_if_no_scipy
  48. def test_scatter_matrix_axis(self):
  49. scatter_matrix = plotting.scatter_matrix
  50. with tm.RNGContext(42):
  51. df = DataFrame(randn(100, 3))
  52. # we are plotting multiples on a sub-plot
  53. with tm.assert_produces_warning(UserWarning):
  54. axes = _check_plot_works(scatter_matrix, filterwarnings='always',
  55. frame=df, range_padding=.1)
  56. axes0_labels = axes[0][0].yaxis.get_majorticklabels()
  57. # GH 5662
  58. expected = ['-2', '0', '2']
  59. self._check_text_labels(axes0_labels, expected)
  60. self._check_ticks_props(
  61. axes, xlabelsize=8, xrot=90, ylabelsize=8, yrot=0)
  62. df[0] = ((df[0] - 2) / 3)
  63. # we are plotting multiples on a sub-plot
  64. with tm.assert_produces_warning(UserWarning):
  65. axes = _check_plot_works(scatter_matrix, filterwarnings='always',
  66. frame=df, range_padding=.1)
  67. axes0_labels = axes[0][0].yaxis.get_majorticklabels()
  68. expected = ['-1.0', '-0.5', '0.0']
  69. self._check_text_labels(axes0_labels, expected)
  70. self._check_ticks_props(
  71. axes, xlabelsize=8, xrot=90, ylabelsize=8, yrot=0)
  72. @pytest.mark.slow
  73. def test_andrews_curves(self, iris):
  74. from pandas.plotting import andrews_curves
  75. from matplotlib import cm
  76. df = iris
  77. _check_plot_works(andrews_curves, frame=df, class_column='Name')
  78. rgba = ('#556270', '#4ECDC4', '#C7F464')
  79. ax = _check_plot_works(andrews_curves, frame=df,
  80. class_column='Name', color=rgba)
  81. self._check_colors(
  82. ax.get_lines()[:10], linecolors=rgba, mapping=df['Name'][:10])
  83. cnames = ['dodgerblue', 'aquamarine', 'seagreen']
  84. ax = _check_plot_works(andrews_curves, frame=df,
  85. class_column='Name', color=cnames)
  86. self._check_colors(
  87. ax.get_lines()[:10], linecolors=cnames, mapping=df['Name'][:10])
  88. ax = _check_plot_works(andrews_curves, frame=df,
  89. class_column='Name', colormap=cm.jet)
  90. cmaps = lmap(cm.jet, np.linspace(0, 1, df['Name'].nunique()))
  91. self._check_colors(
  92. ax.get_lines()[:10], linecolors=cmaps, mapping=df['Name'][:10])
  93. length = 10
  94. df = DataFrame({"A": random.rand(length),
  95. "B": random.rand(length),
  96. "C": random.rand(length),
  97. "Name": ["A"] * length})
  98. _check_plot_works(andrews_curves, frame=df, class_column='Name')
  99. rgba = ('#556270', '#4ECDC4', '#C7F464')
  100. ax = _check_plot_works(andrews_curves, frame=df,
  101. class_column='Name', color=rgba)
  102. self._check_colors(
  103. ax.get_lines()[:10], linecolors=rgba, mapping=df['Name'][:10])
  104. cnames = ['dodgerblue', 'aquamarine', 'seagreen']
  105. ax = _check_plot_works(andrews_curves, frame=df,
  106. class_column='Name', color=cnames)
  107. self._check_colors(
  108. ax.get_lines()[:10], linecolors=cnames, mapping=df['Name'][:10])
  109. ax = _check_plot_works(andrews_curves, frame=df,
  110. class_column='Name', colormap=cm.jet)
  111. cmaps = lmap(cm.jet, np.linspace(0, 1, df['Name'].nunique()))
  112. self._check_colors(
  113. ax.get_lines()[:10], linecolors=cmaps, mapping=df['Name'][:10])
  114. colors = ['b', 'g', 'r']
  115. df = DataFrame({"A": [1, 2, 3],
  116. "B": [1, 2, 3],
  117. "C": [1, 2, 3],
  118. "Name": colors})
  119. ax = andrews_curves(df, 'Name', color=colors)
  120. handles, labels = ax.get_legend_handles_labels()
  121. self._check_colors(handles, linecolors=colors)
  122. with tm.assert_produces_warning(FutureWarning):
  123. andrews_curves(data=df, class_column='Name')
  124. @pytest.mark.slow
  125. def test_parallel_coordinates(self, iris):
  126. from pandas.plotting import parallel_coordinates
  127. from matplotlib import cm
  128. df = iris
  129. ax = _check_plot_works(parallel_coordinates,
  130. frame=df, class_column='Name')
  131. nlines = len(ax.get_lines())
  132. nxticks = len(ax.xaxis.get_ticklabels())
  133. rgba = ('#556270', '#4ECDC4', '#C7F464')
  134. ax = _check_plot_works(parallel_coordinates,
  135. frame=df, class_column='Name', color=rgba)
  136. self._check_colors(
  137. ax.get_lines()[:10], linecolors=rgba, mapping=df['Name'][:10])
  138. cnames = ['dodgerblue', 'aquamarine', 'seagreen']
  139. ax = _check_plot_works(parallel_coordinates,
  140. frame=df, class_column='Name', color=cnames)
  141. self._check_colors(
  142. ax.get_lines()[:10], linecolors=cnames, mapping=df['Name'][:10])
  143. ax = _check_plot_works(parallel_coordinates,
  144. frame=df, class_column='Name', colormap=cm.jet)
  145. cmaps = lmap(cm.jet, np.linspace(0, 1, df['Name'].nunique()))
  146. self._check_colors(
  147. ax.get_lines()[:10], linecolors=cmaps, mapping=df['Name'][:10])
  148. ax = _check_plot_works(parallel_coordinates,
  149. frame=df, class_column='Name', axvlines=False)
  150. assert len(ax.get_lines()) == (nlines - nxticks)
  151. colors = ['b', 'g', 'r']
  152. df = DataFrame({"A": [1, 2, 3],
  153. "B": [1, 2, 3],
  154. "C": [1, 2, 3],
  155. "Name": colors})
  156. ax = parallel_coordinates(df, 'Name', color=colors)
  157. handles, labels = ax.get_legend_handles_labels()
  158. self._check_colors(handles, linecolors=colors)
  159. with tm.assert_produces_warning(FutureWarning):
  160. parallel_coordinates(data=df, class_column='Name')
  161. with tm.assert_produces_warning(FutureWarning):
  162. parallel_coordinates(df, 'Name', colors=colors)
  163. # not sure if this is indicative of a problem
  164. @pytest.mark.filterwarnings("ignore:Attempting to set:UserWarning")
  165. def test_parallel_coordinates_with_sorted_labels(self):
  166. """ For #15908 """
  167. from pandas.plotting import parallel_coordinates
  168. df = DataFrame({"feat": [i for i in range(30)],
  169. "class": [2 for _ in range(10)] +
  170. [3 for _ in range(10)] +
  171. [1 for _ in range(10)]})
  172. ax = parallel_coordinates(df, 'class', sort_labels=True)
  173. polylines, labels = ax.get_legend_handles_labels()
  174. color_label_tuples = \
  175. zip([polyline.get_color() for polyline in polylines], labels)
  176. ordered_color_label_tuples = sorted(color_label_tuples,
  177. key=lambda x: x[1])
  178. prev_next_tupels = zip([i for i in ordered_color_label_tuples[0:-1]],
  179. [i for i in ordered_color_label_tuples[1:]])
  180. for prev, nxt in prev_next_tupels:
  181. # labels and colors are ordered strictly increasing
  182. assert prev[1] < nxt[1] and prev[0] < nxt[0]
  183. @pytest.mark.slow
  184. def test_radviz(self, iris):
  185. from pandas.plotting import radviz
  186. from matplotlib import cm
  187. df = iris
  188. _check_plot_works(radviz, frame=df, class_column='Name')
  189. rgba = ('#556270', '#4ECDC4', '#C7F464')
  190. ax = _check_plot_works(
  191. radviz, frame=df, class_column='Name', color=rgba)
  192. # skip Circle drawn as ticks
  193. patches = [p for p in ax.patches[:20] if p.get_label() != '']
  194. self._check_colors(
  195. patches[:10], facecolors=rgba, mapping=df['Name'][:10])
  196. cnames = ['dodgerblue', 'aquamarine', 'seagreen']
  197. _check_plot_works(radviz, frame=df, class_column='Name', color=cnames)
  198. patches = [p for p in ax.patches[:20] if p.get_label() != '']
  199. self._check_colors(patches, facecolors=cnames, mapping=df['Name'][:10])
  200. _check_plot_works(radviz, frame=df,
  201. class_column='Name', colormap=cm.jet)
  202. cmaps = lmap(cm.jet, np.linspace(0, 1, df['Name'].nunique()))
  203. patches = [p for p in ax.patches[:20] if p.get_label() != '']
  204. self._check_colors(patches, facecolors=cmaps, mapping=df['Name'][:10])
  205. colors = [[0., 0., 1., 1.],
  206. [0., 0.5, 1., 1.],
  207. [1., 0., 0., 1.]]
  208. df = DataFrame({"A": [1, 2, 3],
  209. "B": [2, 1, 3],
  210. "C": [3, 2, 1],
  211. "Name": ['b', 'g', 'r']})
  212. ax = radviz(df, 'Name', color=colors)
  213. handles, labels = ax.get_legend_handles_labels()
  214. self._check_colors(handles, facecolors=colors)
  215. @pytest.mark.slow
  216. def test_subplot_titles(self, iris):
  217. df = iris.drop('Name', axis=1).head()
  218. # Use the column names as the subplot titles
  219. title = list(df.columns)
  220. # Case len(title) == len(df)
  221. plot = df.plot(subplots=True, title=title)
  222. assert [p.get_title() for p in plot] == title
  223. # Case len(title) > len(df)
  224. pytest.raises(ValueError, df.plot, subplots=True,
  225. title=title + ["kittens > puppies"])
  226. # Case len(title) < len(df)
  227. pytest.raises(ValueError, df.plot, subplots=True, title=title[:2])
  228. # Case subplots=False and title is of type list
  229. pytest.raises(ValueError, df.plot, subplots=False, title=title)
  230. # Case df with 3 numeric columns but layout of (2,2)
  231. plot = df.drop('SepalWidth', axis=1).plot(subplots=True, layout=(2, 2),
  232. title=title[:-1])
  233. title_list = [ax.get_title() for sublist in plot for ax in sublist]
  234. assert title_list == title[:3] + ['']
  235. def test_get_standard_colors_random_seed(self):
  236. # GH17525
  237. df = DataFrame(np.zeros((10, 10)))
  238. # Make sure that the random seed isn't reset by _get_standard_colors
  239. plotting.parallel_coordinates(df, 0)
  240. rand1 = random.random()
  241. plotting.parallel_coordinates(df, 0)
  242. rand2 = random.random()
  243. assert rand1 != rand2
  244. # Make sure it produces the same colors every time it's called
  245. from pandas.plotting._style import _get_standard_colors
  246. color1 = _get_standard_colors(1, color_type='random')
  247. color2 = _get_standard_colors(1, color_type='random')
  248. assert color1 == color2
  249. def test_get_standard_colors_default_num_colors(self):
  250. from pandas.plotting._style import _get_standard_colors
  251. # Make sure the default color_types returns the specified amount
  252. color1 = _get_standard_colors(1, color_type='default')
  253. color2 = _get_standard_colors(9, color_type='default')
  254. color3 = _get_standard_colors(20, color_type='default')
  255. assert len(color1) == 1
  256. assert len(color2) == 9
  257. assert len(color3) == 20
  258. def test_plot_single_color(self):
  259. # Example from #20585. All 3 bars should have the same color
  260. df = DataFrame({'account-start': ['2017-02-03', '2017-03-03',
  261. '2017-01-01'],
  262. 'client': ['Alice Anders', 'Bob Baker',
  263. 'Charlie Chaplin'],
  264. 'balance': [-1432.32, 10.43, 30000.00],
  265. 'db-id': [1234, 2424, 251],
  266. 'proxy-id': [525, 1525, 2542],
  267. 'rank': [52, 525, 32],
  268. })
  269. ax = df.client.value_counts().plot.bar()
  270. colors = lmap(lambda rect: rect.get_facecolor(),
  271. ax.get_children()[0:3])
  272. assert all(color == colors[0] for color in colors)
  273. def test_get_standard_colors_no_appending(self):
  274. # GH20726
  275. # Make sure not to add more colors so that matplotlib can cycle
  276. # correctly.
  277. from matplotlib import cm
  278. color_before = cm.gnuplot(range(5))
  279. color_after = plotting._style._get_standard_colors(
  280. 1, color=color_before)
  281. assert len(color_after) == len(color_before)
  282. df = DataFrame(np.random.randn(48, 4), columns=list("ABCD"))
  283. color_list = cm.gnuplot(np.linspace(0, 1, 16))
  284. p = df.A.plot.bar(figsize=(16, 7), color=color_list)
  285. assert (p.patches[1].get_facecolor()
  286. == p.patches[17].get_facecolor())