From 096f6be60764188d759892e82d08129468e4d77e Mon Sep 17 00:00:00 2001 From: Yury Mikhaylov <44315225+Mikhaylov-yv@users.noreply.github.com> Date: Fri, 13 Nov 2020 05:51:07 +0300 Subject: [PATCH] TST: split up tests/plotting/test_frame.py into subdir & modules #34769 (#37655) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Moving the file test_frame.py to a new directory * Сreated file test_frame_color.py * Transfer tests of test_frame.py to test_frame_color.py * PEP 8 fixes * Transfer tests of test_frame.py to test_frame_groupby.py and test_frame_subplots.py * Removing unnecessary imports * PEP 8 fixes * Fixed class name * Transfer tests of test_frame.py to test_frame_subplots.py * Transfer tests of test_frame.py to test_frame_groupby.py, test_frame_subplots.py, test_frame_color.py * Changed class names * Removed unnecessary imports * Removed import * catch FutureWarnings (#37587) * TST/REF: collect indexing tests by method (#37590) * REF: prelims for single-path setitem_with_indexer (#37588) * ENH: __repr__ for 2D DTA/TDA (#37164) * CLN: de-duplicate _validate_where_value with _validate_setitem_value (#37595) * TST/REF: collect tests by method (#37589) * TST/REF: move remaining setitem tests from test_timeseries * TST/REF: rehome test_timezones test * move misplaced arithmetic test * collect tests by method * move misplaced file * REF: Categorical.is_dtype_equal -> categories_match_up_to_permutation (#37545) * CLN refactor non-core (#37580) * refactor core/computation (#37585) * TST/REF: share method tests between DataFrame and Series (#37596) * BUG: Index.where casting ints to str (#37591) * REF: IntervalArray comparisons (#37124) * regression fix for merging DF with datetime index with empty DF (#36897) * ERR: fix error message in Period for invalid frequency (#37602) * CLN: remove rebox_native (#37608) * TST/REF: tests.generic (#37618) * TST: collect tests by method (#37617) * TST/REF: collect test_timeseries tests by method * misplaced DataFrame.values tst * misplaced dataframe.values test * collect test by method * TST/REF: share tests across Series/DataFrame (#37616) * Gh 36562 typeerror comparison not supported between float and str (#37096) * docs: fix punctuation (#37612) * REGR: pd.to_hdf(..., dropna=True) not dropping missing rows (#37564) * parametrize set_axis tests (#37619) * CLN: clean color selection in _matplotlib/style (#37203) * DEPR: DataFrame/Series.slice_shift (#37601) * REF: re-use validate_setitem_value in Categorical.fillna (#37597) * PERF: release gil for ewma_time (#37389) * BUG: Groupy dropped nan groups from result when grouping over single column (#36842) * ENH: implement timeszones support for read_json(orient='table') and astype() from 'object' (#35973) * REF/BUG/TYP: read_csv shouldn't close user-provided file handles (#36997) * BUG/REF: read_csv shouldn't close user-provided file handles * get_handle: typing, returns is_wrapped, use dataclass, and make sure that all created handlers are returned * remove unused imports * added IOHandleArgs.close * added IOArgs.close * mostly comments * move memory_map from TextReader to CParserWrapper * moved IOArgs and IOHandles * more comments Co-authored-by: Jeff Reback * more typing checks to pre-commit (#37539) * TST: 32bit dtype compat test_groupby_dropna (#37623) * BUG: Metadata propagation for groupby iterator (#37461) * BUG: read-only values in cython funcs (#37613) * CLN refactor core/arrays (#37581) * Fixed Metadata Propogation in DataFrame (#37381) * TYP: add Shape alias to pandas._typing (#37128) * DOC: Fix typo (#37630) * CLN: parametrize test_nat_comparisons (#37195) * dataframe dataclass docstring updated (#37632) * refactor core/groupby (#37583) * BUG: set index of DataFrame.apply(f) when f returns dict (#37544) (#37606) * BUG: to_dict should return a native datetime object for NumPy backed dataframes (#37571) * ENH: memory_map for compressed files (#37621) * DOC: add example & prose of slicing with labels when index has duplicate labels (#36814) * DOC: add example & prose of slicing with labels when index has duplicate labels #36251 * DOC: proofread the sentence. Co-authored-by: Jun Kudo * DOC: Fix typo (#37636) "columns(s)" sounded odd, I believe it was supposed to be just "column(s)". * CI: troubleshoot win py38 builds (#37652) * TST/REF: collect indexing tests by method (#37638) * TST/REF: collect tests for get_numeric_data (#37634) * misplaced loc test * TST/REF: collect get_numeric_data tests * REF: de-duplicate _validate_insert_value with _validate_scalar (#37640) * CI: catch windows py38 OSError (#37659) * share test (#37679) * TST: match matplotlib warning message (#37666) * TST: match matplotlib warning message * TST: match full message * pd.Series.loc.__getitem__ promotes to float64 instead of raising KeyError (#37687) * REF/TST: misplaced Categorical tests (#37678) * REF/TST: collect indexing tests by method (#37677) * CLN: only call _wrap_results one place in nanmedian (#37673) * TYP: Index._concat (#37671) * BUG: CategoricalIndex.equals casting non-categories to np.nan (#37667) * CLN: _replace_single (#37683) * REF: simplify _replace_single by noting regex kwarg is bool * Annotate * CLN: remove never-False convert kwarg * TYP: make more internal funcs keyword-only (#37688) * REF: make Series._replace_single a regular method (#37691) * REF: simplify cycling through colors (#37664) * REF: implement _wrap_reduction_result (#37660) * BUG: preserve fold in Timestamp.replace (#37644) * CLN: Clean indexing tests (#37689) * TST: fix warning for pie chart (#37669) * PERF: reverted change from commit 7d257c6 to solve issue #37081 (#37426) * DataFrameGroupby.boxplot fails when subplots=False (#28102) * ENH: Improve error reporting for wrong merge cols (#37547) * Transfer tests of test_frame.py to test_frame_color.py * PEP8 * Fixes for linter * Сhange pd.DateFrame to DateFrame * Move inconsistent namespace check to pre-commit, fixup more files (#37662) * check for inconsistent namespace usage * doc * typos * verbose regex * use verbose flag * use verbose flag * match both directions * add test * don't import annotations from future * update extra couple of cases * :truck: rename * typing * don't use subprocess * don't type tests * use pathlib * REF: simplify NDFrame.replace, ObjectBlock.replace (#37704) * REF: implement Categorical.encode_with_my_categories (#37650) * REF: implement Categorical.encode_with_my_categories * privatize * BUG: unpickling modifies Block.ndim (#37657) * REF: dont support dt64tz in nanmean (#37658) * CLN: Simplify groupby head/tail tests (#37702) * Bug in loc raised for numeric label even when label is in Index (#37675) * REF: implement replace_regex, remove unreachable branch in ObjectBlock.replace (#37696) * TYP: Check untyped defs (except vendored) (#37556) * REF: remove ObjectBlock._replace_single (#37710) * Transfer tests of test_frame.py to test_frame_color.py * TST/REF: collect indexing tests by method (#37590) * PEP8 * Сhange DateFrame to pd.DateFrame * Сhange pd.DateFrame to DateFrame * Removing imports * Bug fixes * Bug fixes * Fix incorrect merge * test_frame_color.py edit * Transfer tests of test_frame.py to test_frame_color.py, test_frame_groupby.py and test_frame_subplots.py * Removing unnecessary imports * PEP8 * # Conflicts: # pandas/tests/plotting/frame/test_frame.py # pandas/tests/plotting/frame/test_frame_color.py # pandas/tests/plotting/frame/test_frame_subplots.py * Moving the file test_frame.py to a new directory * Transfer tests of test_frame.py to test_frame_color.py, test_frame_groupby.py and test_frame_subplots.py * Removing unnecessary imports * PEP8 * CLN: clean categorical indexes tests (#37721) * Fix merge error * PEP 8 fixes * Fix merge error * Removing unnecessary imports * PEP 8 fixes * Fixed class name * Transfer tests of test_frame.py to test_frame_subplots.py * Transfer tests of test_frame.py to test_frame_groupby.py, test_frame_subplots.py, test_frame_color.py * Changed class names * Removed unnecessary imports * Removed import * TST/REF: collect indexing tests by method (#37590) * TST: match matplotlib warning message (#37666) * TST: match matplotlib warning message * TST: match full message * TST: fix warning for pie chart (#37669) * Transfer tests of test_frame.py to test_frame_color.py * PEP8 * Fixes for linter * Сhange pd.DateFrame to DateFrame * Transfer tests of test_frame.py to test_frame_color.py * PEP8 * Сhange DateFrame to pd.DateFrame * Сhange pd.DateFrame to DateFrame * Removing imports * Bug fixes * Bug fixes * Fix incorrect merge * test_frame_color.py edit * Fix merge error * Fix merge error * Removing unnecessary features * Resolving Commit Conflicts daf999f 365d843 * black fix Co-authored-by: jbrockmendel Co-authored-by: Marco Gorelli Co-authored-by: Philip Cerles Co-authored-by: Joris Van den Bossche Co-authored-by: Sven Co-authored-by: Micael Jarniac Co-authored-by: Andrew Wieteska <48889395+arw2019@users.noreply.github.com> Co-authored-by: Maxim Ivanov <41443370+ivanovmg@users.noreply.github.com> Co-authored-by: Erfan Nariman <34067903+erfannariman@users.noreply.github.com> Co-authored-by: Fangchen Li Co-authored-by: patrick <61934744+phofl@users.noreply.github.com> Co-authored-by: attack68 <24256554+attack68@users.noreply.github.com> Co-authored-by: Torsten Wörtwein Co-authored-by: Jeff Reback Co-authored-by: Janus Co-authored-by: Joel Whittier Co-authored-by: taytzehao Co-authored-by: ma3da <34522496+ma3da@users.noreply.github.com> Co-authored-by: junk Co-authored-by: Jun Kudo Co-authored-by: Alex Kirko Co-authored-by: Yassir Karroum Co-authored-by: Kaiqi Dong Co-authored-by: Richard Shadrach <45562402+rhshadrach@users.noreply.github.com> Co-authored-by: Simon Hawkins --- pandas/tests/plotting/frame/__init__.py | 0 .../tests/plotting/{ => frame}/test_frame.py | 1327 ----------------- .../tests/plotting/frame/test_frame_color.py | 655 ++++++++ .../plotting/frame/test_frame_groupby.py | 90 ++ .../plotting/frame/test_frame_subplots.py | 677 +++++++++ 5 files changed, 1422 insertions(+), 1327 deletions(-) create mode 100644 pandas/tests/plotting/frame/__init__.py rename pandas/tests/plotting/{ => frame}/test_frame.py (61%) create mode 100644 pandas/tests/plotting/frame/test_frame_color.py create mode 100644 pandas/tests/plotting/frame/test_frame_groupby.py create mode 100644 pandas/tests/plotting/frame/test_frame_subplots.py diff --git a/pandas/tests/plotting/frame/__init__.py b/pandas/tests/plotting/frame/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/pandas/tests/plotting/test_frame.py b/pandas/tests/plotting/frame/test_frame.py similarity index 61% rename from pandas/tests/plotting/test_frame.py rename to pandas/tests/plotting/frame/test_frame.py index bb7507243412f..3c43e0b693a1b 100644 --- a/pandas/tests/plotting/test_frame.py +++ b/pandas/tests/plotting/frame/test_frame.py @@ -39,14 +39,6 @@ def setup_method(self, method): } ) - def _assert_ytickslabels_visibility(self, axes, expected): - for ax, exp in zip(axes, expected): - self._check_visible(ax.get_yticklabels(), visible=exp) - - def _assert_xtickslabels_visibility(self, axes, expected): - for ax, exp in zip(axes, expected): - self._check_visible(ax.get_xticklabels(), visible=exp) - @pytest.mark.slow def test_plot(self): from pandas.plotting._matplotlib.compat import mpl_ge_3_1_0 @@ -174,74 +166,6 @@ def test_integer_array_plot(self): _check_plot_works(df.plot.scatter, x="x", y="y") _check_plot_works(df.plot.hexbin, x="x", y="y") - def test_mpl2_color_cycle_str(self): - # GH 15516 - df = DataFrame(np.random.randn(10, 3), columns=["a", "b", "c"]) - colors = ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"] - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always", "MatplotlibDeprecationWarning") - - for color in colors: - _check_plot_works(df.plot, color=color) - - # if warning is raised, check that it is the exact problematic one - # GH 36972 - if w: - match = "Support for uppercase single-letter colors is deprecated" - warning_message = str(w[0].message) - msg = "MatplotlibDeprecationWarning related to CN colors was raised" - assert match not in warning_message, msg - - def test_color_single_series_list(self): - # GH 3486 - df = DataFrame({"A": [1, 2, 3]}) - _check_plot_works(df.plot, color=["red"]) - - @pytest.mark.parametrize("color", [(1, 0, 0), (1, 0, 0, 0.5)]) - def test_rgb_tuple_color(self, color): - # GH 16695 - df = DataFrame({"x": [1, 2], "y": [3, 4]}) - _check_plot_works(df.plot, x="x", y="y", color=color) - - def test_color_empty_string(self): - df = DataFrame(np.random.randn(10, 2)) - with pytest.raises(ValueError): - df.plot(color="") - - def test_color_and_style_arguments(self): - df = DataFrame({"x": [1, 2], "y": [3, 4]}) - # passing both 'color' and 'style' arguments should be allowed - # if there is no color symbol in the style strings: - ax = df.plot(color=["red", "black"], style=["-", "--"]) - # check that the linestyles are correctly set: - linestyle = [line.get_linestyle() for line in ax.lines] - assert linestyle == ["-", "--"] - # check that the colors are correctly set: - color = [line.get_color() for line in ax.lines] - assert color == ["red", "black"] - # passing both 'color' and 'style' arguments should not be allowed - # if there is a color symbol in the style strings: - with pytest.raises(ValueError): - df.plot(color=["red", "black"], style=["k-", "r--"]) - - @pytest.mark.parametrize( - "color, expected", - [ - ("green", ["green"] * 4), - (["yellow", "red", "green", "blue"], ["yellow", "red", "green", "blue"]), - ], - ) - def test_color_and_marker(self, color, expected): - # GH 21003 - df = DataFrame(np.random.random((7, 4))) - ax = df.plot(color=color, style="d--") - # check colors - result = [i.get_color() for i in ax.lines] - assert result == expected - # check markers and linestyles - assert all(i.get_linestyle() == "--" for i in ax.lines) - assert all(i.get_marker() == "d" for i in ax.lines) - def test_nonnumeric_exclude(self): df = DataFrame({"A": ["x", "y", "z"], "B": [1, 2, 3]}) ax = df.plot() @@ -411,405 +335,6 @@ def test_unsorted_index_lims(self): assert xmin <= np.nanmin(lines[0].get_data()[0]) assert xmax >= np.nanmax(lines[0].get_data()[0]) - @pytest.mark.slow - def test_subplots(self): - df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) - - for kind in ["bar", "barh", "line", "area"]: - axes = df.plot(kind=kind, subplots=True, sharex=True, legend=True) - self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) - assert axes.shape == (3,) - - for ax, column in zip(axes, df.columns): - self._check_legend_labels(ax, labels=[pprint_thing(column)]) - - for ax in axes[:-2]: - self._check_visible(ax.xaxis) # xaxis must be visible for grid - self._check_visible(ax.get_xticklabels(), visible=False) - if not (kind == "bar" and self.mpl_ge_3_1_0): - # change https://github.com/pandas-dev/pandas/issues/26714 - self._check_visible(ax.get_xticklabels(minor=True), visible=False) - self._check_visible(ax.xaxis.get_label(), visible=False) - self._check_visible(ax.get_yticklabels()) - - self._check_visible(axes[-1].xaxis) - self._check_visible(axes[-1].get_xticklabels()) - self._check_visible(axes[-1].get_xticklabels(minor=True)) - self._check_visible(axes[-1].xaxis.get_label()) - self._check_visible(axes[-1].get_yticklabels()) - - axes = df.plot(kind=kind, subplots=True, sharex=False) - for ax in axes: - self._check_visible(ax.xaxis) - self._check_visible(ax.get_xticklabels()) - self._check_visible(ax.get_xticklabels(minor=True)) - self._check_visible(ax.xaxis.get_label()) - self._check_visible(ax.get_yticklabels()) - - axes = df.plot(kind=kind, subplots=True, legend=False) - for ax in axes: - assert ax.get_legend() is None - - @pytest.mark.parametrize( - "kwargs, expected", - [ - # behavior without keyword - ({}, [True, False, True, False]), - # set sharey=True should be identical - ({"sharey": True}, [True, False, True, False]), - # sharey=False, all yticklabels should be visible - ({"sharey": False}, [True, True, True, True]), - ], - ) - def test_groupby_boxplot_sharey(self, kwargs, expected): - # https://github.com/pandas-dev/pandas/issues/20968 - # sharey can now be switched check whether the right - # pair of axes is turned on or off - df = DataFrame( - { - "a": [-1.43, -0.15, -3.70, -1.43, -0.14], - "b": [0.56, 0.84, 0.29, 0.56, 0.85], - "c": [0, 1, 2, 3, 1], - }, - index=[0, 1, 2, 3, 4], - ) - axes = df.groupby("c").boxplot(**kwargs) - self._assert_ytickslabels_visibility(axes, expected) - - @pytest.mark.parametrize( - "kwargs, expected", - [ - # behavior without keyword - ({}, [True, True, True, True]), - # set sharex=False should be identical - ({"sharex": False}, [True, True, True, True]), - # sharex=True, xticklabels should be visible - # only for bottom plots - ({"sharex": True}, [False, False, True, True]), - ], - ) - def test_groupby_boxplot_sharex(self, kwargs, expected): - # https://github.com/pandas-dev/pandas/issues/20968 - # sharex can now be switched check whether the right - # pair of axes is turned on or off - df = DataFrame( - { - "a": [-1.43, -0.15, -3.70, -1.43, -0.14], - "b": [0.56, 0.84, 0.29, 0.56, 0.85], - "c": [0, 1, 2, 3, 1], - }, - index=[0, 1, 2, 3, 4], - ) - axes = df.groupby("c").boxplot(**kwargs) - self._assert_xtickslabels_visibility(axes, expected) - - @pytest.mark.slow - def test_subplots_timeseries(self): - idx = date_range(start="2014-07-01", freq="M", periods=10) - df = DataFrame(np.random.rand(10, 3), index=idx) - - for kind in ["line", "area"]: - axes = df.plot(kind=kind, subplots=True, sharex=True) - self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) - - for ax in axes[:-2]: - # GH 7801 - self._check_visible(ax.xaxis) # xaxis must be visible for grid - self._check_visible(ax.get_xticklabels(), visible=False) - self._check_visible(ax.get_xticklabels(minor=True), visible=False) - self._check_visible(ax.xaxis.get_label(), visible=False) - self._check_visible(ax.get_yticklabels()) - - self._check_visible(axes[-1].xaxis) - self._check_visible(axes[-1].get_xticklabels()) - self._check_visible(axes[-1].get_xticklabels(minor=True)) - self._check_visible(axes[-1].xaxis.get_label()) - self._check_visible(axes[-1].get_yticklabels()) - self._check_ticks_props(axes, xrot=0) - - axes = df.plot(kind=kind, subplots=True, sharex=False, rot=45, fontsize=7) - for ax in axes: - self._check_visible(ax.xaxis) - self._check_visible(ax.get_xticklabels()) - self._check_visible(ax.get_xticklabels(minor=True)) - self._check_visible(ax.xaxis.get_label()) - self._check_visible(ax.get_yticklabels()) - self._check_ticks_props(ax, xlabelsize=7, xrot=45, ylabelsize=7) - - def test_subplots_timeseries_y_axis(self): - # GH16953 - data = { - "numeric": np.array([1, 2, 5]), - "timedelta": [ - pd.Timedelta(-10, unit="s"), - pd.Timedelta(10, unit="m"), - pd.Timedelta(10, unit="h"), - ], - "datetime_no_tz": [ - pd.to_datetime("2017-08-01 00:00:00"), - pd.to_datetime("2017-08-01 02:00:00"), - pd.to_datetime("2017-08-02 00:00:00"), - ], - "datetime_all_tz": [ - pd.to_datetime("2017-08-01 00:00:00", utc=True), - pd.to_datetime("2017-08-01 02:00:00", utc=True), - pd.to_datetime("2017-08-02 00:00:00", utc=True), - ], - "text": ["This", "should", "fail"], - } - testdata = DataFrame(data) - - y_cols = ["numeric", "timedelta", "datetime_no_tz", "datetime_all_tz"] - for col in y_cols: - ax = testdata.plot(y=col) - result = ax.get_lines()[0].get_data()[1] - expected = testdata[col].values - assert (result == expected).all() - - msg = "no numeric data to plot" - with pytest.raises(TypeError, match=msg): - testdata.plot(y="text") - - @pytest.mark.xfail(reason="not support for period, categorical, datetime_mixed_tz") - def test_subplots_timeseries_y_axis_not_supported(self): - """ - This test will fail for: - period: - since period isn't yet implemented in ``select_dtypes`` - and because it will need a custom value converter + - tick formatter (as was done for x-axis plots) - - categorical: - because it will need a custom value converter + - tick formatter (also doesn't work for x-axis, as of now) - - datetime_mixed_tz: - because of the way how pandas handles ``Series`` of - ``datetime`` objects with different timezone, - generally converting ``datetime`` objects in a tz-aware - form could help with this problem - """ - data = { - "numeric": np.array([1, 2, 5]), - "period": [ - pd.Period("2017-08-01 00:00:00", freq="H"), - pd.Period("2017-08-01 02:00", freq="H"), - pd.Period("2017-08-02 00:00:00", freq="H"), - ], - "categorical": pd.Categorical( - ["c", "b", "a"], categories=["a", "b", "c"], ordered=False - ), - "datetime_mixed_tz": [ - pd.to_datetime("2017-08-01 00:00:00", utc=True), - pd.to_datetime("2017-08-01 02:00:00"), - pd.to_datetime("2017-08-02 00:00:00"), - ], - } - testdata = DataFrame(data) - ax_period = testdata.plot(x="numeric", y="period") - assert ( - ax_period.get_lines()[0].get_data()[1] == testdata["period"].values - ).all() - ax_categorical = testdata.plot(x="numeric", y="categorical") - assert ( - ax_categorical.get_lines()[0].get_data()[1] - == testdata["categorical"].values - ).all() - ax_datetime_mixed_tz = testdata.plot(x="numeric", y="datetime_mixed_tz") - assert ( - ax_datetime_mixed_tz.get_lines()[0].get_data()[1] - == testdata["datetime_mixed_tz"].values - ).all() - - @pytest.mark.slow - def test_subplots_layout_multi_column(self): - # GH 6667 - df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) - - axes = df.plot(subplots=True, layout=(2, 2)) - self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) - assert axes.shape == (2, 2) - - axes = df.plot(subplots=True, layout=(-1, 2)) - self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) - assert axes.shape == (2, 2) - - axes = df.plot(subplots=True, layout=(2, -1)) - self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) - assert axes.shape == (2, 2) - - axes = df.plot(subplots=True, layout=(1, 4)) - self._check_axes_shape(axes, axes_num=3, layout=(1, 4)) - assert axes.shape == (1, 4) - - axes = df.plot(subplots=True, layout=(-1, 4)) - self._check_axes_shape(axes, axes_num=3, layout=(1, 4)) - assert axes.shape == (1, 4) - - axes = df.plot(subplots=True, layout=(4, -1)) - self._check_axes_shape(axes, axes_num=3, layout=(4, 1)) - assert axes.shape == (4, 1) - - with pytest.raises(ValueError): - df.plot(subplots=True, layout=(1, 1)) - with pytest.raises(ValueError): - df.plot(subplots=True, layout=(-1, -1)) - - @pytest.mark.slow - @pytest.mark.parametrize( - "kwargs, expected_axes_num, expected_layout, expected_shape", - [ - ({}, 1, (1, 1), (1,)), - ({"layout": (3, 3)}, 1, (3, 3), (3, 3)), - ], - ) - def test_subplots_layout_single_column( - self, kwargs, expected_axes_num, expected_layout, expected_shape - ): - # GH 6667 - df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10])) - axes = df.plot(subplots=True, **kwargs) - self._check_axes_shape( - axes, - axes_num=expected_axes_num, - layout=expected_layout, - ) - assert axes.shape == expected_shape - - @pytest.mark.slow - def test_subplots_warnings(self): - # GH 9464 - with tm.assert_produces_warning(None): - df = DataFrame(np.random.randn(100, 4)) - df.plot(subplots=True, layout=(3, 2)) - - df = DataFrame( - np.random.randn(100, 4), index=date_range("1/1/2000", periods=100) - ) - df.plot(subplots=True, layout=(3, 2)) - - @pytest.mark.slow - def test_subplots_multiple_axes(self): - # GH 5353, 6970, GH 7069 - fig, axes = self.plt.subplots(2, 3) - df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) - - returned = df.plot(subplots=True, ax=axes[0], sharex=False, sharey=False) - self._check_axes_shape(returned, axes_num=3, layout=(1, 3)) - assert returned.shape == (3,) - assert returned[0].figure is fig - # draw on second row - returned = df.plot(subplots=True, ax=axes[1], sharex=False, sharey=False) - self._check_axes_shape(returned, axes_num=3, layout=(1, 3)) - assert returned.shape == (3,) - assert returned[0].figure is fig - self._check_axes_shape(axes, axes_num=6, layout=(2, 3)) - tm.close() - - with pytest.raises(ValueError): - fig, axes = self.plt.subplots(2, 3) - # pass different number of axes from required - df.plot(subplots=True, ax=axes) - - # pass 2-dim axes and invalid layout - # invalid lauout should not affect to input and return value - # (show warning is tested in - # TestDataFrameGroupByPlots.test_grouped_box_multiple_axes - fig, axes = self.plt.subplots(2, 2) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", UserWarning) - df = DataFrame(np.random.rand(10, 4), index=list(string.ascii_letters[:10])) - - returned = df.plot( - subplots=True, ax=axes, layout=(2, 1), sharex=False, sharey=False - ) - self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) - assert returned.shape == (4,) - - returned = df.plot( - subplots=True, ax=axes, layout=(2, -1), sharex=False, sharey=False - ) - self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) - assert returned.shape == (4,) - - returned = df.plot( - subplots=True, ax=axes, layout=(-1, 2), sharex=False, sharey=False - ) - self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) - assert returned.shape == (4,) - - # single column - fig, axes = self.plt.subplots(1, 1) - df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10])) - - axes = df.plot(subplots=True, ax=[axes], sharex=False, sharey=False) - self._check_axes_shape(axes, axes_num=1, layout=(1, 1)) - assert axes.shape == (1,) - - def test_subplots_ts_share_axes(self): - # GH 3964 - fig, axes = self.plt.subplots(3, 3, sharex=True, sharey=True) - self.plt.subplots_adjust(left=0.05, right=0.95, hspace=0.3, wspace=0.3) - df = DataFrame( - np.random.randn(10, 9), - index=date_range(start="2014-07-01", freq="M", periods=10), - ) - for i, ax in enumerate(axes.ravel()): - df[i].plot(ax=ax, fontsize=5) - - # Rows other than bottom should not be visible - for ax in axes[0:-1].ravel(): - self._check_visible(ax.get_xticklabels(), visible=False) - - # Bottom row should be visible - for ax in axes[-1].ravel(): - self._check_visible(ax.get_xticklabels(), visible=True) - - # First column should be visible - for ax in axes[[0, 1, 2], [0]].ravel(): - self._check_visible(ax.get_yticklabels(), visible=True) - - # Other columns should not be visible - for ax in axes[[0, 1, 2], [1]].ravel(): - self._check_visible(ax.get_yticklabels(), visible=False) - for ax in axes[[0, 1, 2], [2]].ravel(): - self._check_visible(ax.get_yticklabels(), visible=False) - - def test_subplots_sharex_axes_existing_axes(self): - # GH 9158 - d = {"A": [1.0, 2.0, 3.0, 4.0], "B": [4.0, 3.0, 2.0, 1.0], "C": [5, 1, 3, 4]} - df = DataFrame(d, index=date_range("2014 10 11", "2014 10 14")) - - axes = df[["A", "B"]].plot(subplots=True) - df["C"].plot(ax=axes[0], secondary_y=True) - - self._check_visible(axes[0].get_xticklabels(), visible=False) - self._check_visible(axes[1].get_xticklabels(), visible=True) - for ax in axes.ravel(): - self._check_visible(ax.get_yticklabels(), visible=True) - - @pytest.mark.slow - def test_subplots_dup_columns(self): - # GH 10962 - df = DataFrame(np.random.rand(5, 5), columns=list("aaaaa")) - axes = df.plot(subplots=True) - for ax in axes: - self._check_legend_labels(ax, labels=["a"]) - assert len(ax.lines) == 1 - tm.close() - - axes = df.plot(subplots=True, secondary_y="a") - for ax in axes: - # (right) is only attached when subplots=False - self._check_legend_labels(ax, labels=["a"]) - assert len(ax.lines) == 1 - tm.close() - - ax = df.plot(secondary_y="a") - self._check_legend_labels(ax, labels=["a (right)"] * 5) - assert len(ax.lines) == 0 - assert len(ax.right_ax.lines) == 5 - def test_negative_log(self): df = -DataFrame( np.random.rand(6, 4), @@ -952,60 +477,6 @@ def test_area_lim(self): ymin, ymax = ax.get_ylim() assert ymax == 0 - @pytest.mark.slow - def test_bar_colors(self): - import matplotlib.pyplot as plt - - default_colors = self._unpack_cycler(plt.rcParams) - - df = DataFrame(np.random.randn(5, 5)) - ax = df.plot.bar() - self._check_colors(ax.patches[::5], facecolors=default_colors[:5]) - tm.close() - - custom_colors = "rgcby" - ax = df.plot.bar(color=custom_colors) - self._check_colors(ax.patches[::5], facecolors=custom_colors) - tm.close() - - from matplotlib import cm - - # Test str -> colormap functionality - ax = df.plot.bar(colormap="jet") - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] - self._check_colors(ax.patches[::5], facecolors=rgba_colors) - tm.close() - - # Test colormap functionality - ax = df.plot.bar(colormap=cm.jet) - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] - self._check_colors(ax.patches[::5], facecolors=rgba_colors) - tm.close() - - ax = df.loc[:, [0]].plot.bar(color="DodgerBlue") - self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"]) - tm.close() - - ax = df.plot(kind="bar", color="green") - self._check_colors(ax.patches[::5], facecolors=["green"] * 5) - tm.close() - - def test_bar_user_colors(self): - df = DataFrame( - {"A": range(4), "B": range(1, 5), "color": ["red", "blue", "blue", "red"]} - ) - # This should *only* work when `y` is specified, else - # we use one color per column - ax = df.plot.bar(y="A", color=df["color"]) - result = [p.get_facecolor() for p in ax.patches] - expected = [ - (1.0, 0.0, 0.0, 1.0), - (0.0, 0.0, 1.0, 1.0), - (0.0, 0.0, 1.0, 1.0), - (1.0, 0.0, 0.0, 1.0), - ] - assert result == expected - @pytest.mark.slow def test_bar_linewidth(self): df = DataFrame(np.random.randn(5, 5)) @@ -1065,42 +536,6 @@ def test_bar_barwidth(self): for r in ax.patches: assert r.get_height() == width - @pytest.mark.slow - @pytest.mark.parametrize( - "kwargs", - [ - {"kind": "bar", "stacked": False}, - {"kind": "bar", "stacked": True}, - {"kind": "barh", "stacked": False}, - {"kind": "barh", "stacked": True}, - {"kind": "bar", "subplots": True}, - {"kind": "barh", "subplots": True}, - ], - ) - def test_bar_barwidth_position(self, kwargs): - df = DataFrame(np.random.randn(5, 5)) - self._check_bar_alignment(df, width=0.9, position=0.2, **kwargs) - - @pytest.mark.slow - def test_bar_barwidth_position_int(self): - # GH 12979 - df = DataFrame(np.random.randn(5, 5)) - - for w in [1, 1.0]: - ax = df.plot.bar(stacked=True, width=w) - ticks = ax.xaxis.get_ticklocs() - tm.assert_numpy_array_equal(ticks, np.array([0, 1, 2, 3, 4])) - assert ax.get_xlim() == (-0.75, 4.75) - # check left-edge of bars - assert ax.patches[0].get_x() == -0.5 - assert ax.patches[-1].get_x() == 3.5 - - self._check_bar_alignment(df, kind="bar", stacked=True, width=1) - self._check_bar_alignment(df, kind="barh", stacked=False, width=1) - self._check_bar_alignment(df, kind="barh", stacked=True, width=1) - self._check_bar_alignment(df, kind="bar", subplots=True, width=1) - self._check_bar_alignment(df, kind="barh", subplots=True, width=1) - @pytest.mark.slow def test_bar_bottom_left(self): df = DataFrame(np.random.rand(5, 5)) @@ -1226,60 +661,6 @@ def test_scatterplot_object_data(self): _check_plot_works(df.plot.scatter, x="a", y="b") _check_plot_works(df.plot.scatter, x=0, y=1) - @pytest.mark.slow - def test_if_scatterplot_colorbar_affects_xaxis_visibility(self): - # addressing issue #10611, to ensure colobar does not - # interfere with x-axis label and ticklabels with - # ipython inline backend. - random_array = np.random.random((1000, 3)) - df = DataFrame(random_array, columns=["A label", "B label", "C label"]) - - ax1 = df.plot.scatter(x="A label", y="B label") - ax2 = df.plot.scatter(x="A label", y="B label", c="C label") - - vis1 = [vis.get_visible() for vis in ax1.xaxis.get_minorticklabels()] - vis2 = [vis.get_visible() for vis in ax2.xaxis.get_minorticklabels()] - assert vis1 == vis2 - - vis1 = [vis.get_visible() for vis in ax1.xaxis.get_majorticklabels()] - vis2 = [vis.get_visible() for vis in ax2.xaxis.get_majorticklabels()] - assert vis1 == vis2 - - assert ( - ax1.xaxis.get_label().get_visible() == ax2.xaxis.get_label().get_visible() - ) - - @pytest.mark.slow - def test_if_hexbin_xaxis_label_is_visible(self): - # addressing issue #10678, to ensure colobar does not - # interfere with x-axis label and ticklabels with - # ipython inline backend. - random_array = np.random.random((1000, 3)) - df = DataFrame(random_array, columns=["A label", "B label", "C label"]) - - ax = df.plot.hexbin("A label", "B label", gridsize=12) - assert all(vis.get_visible() for vis in ax.xaxis.get_minorticklabels()) - assert all(vis.get_visible() for vis in ax.xaxis.get_majorticklabels()) - assert ax.xaxis.get_label().get_visible() - - @pytest.mark.slow - def test_if_scatterplot_colorbars_are_next_to_parent_axes(self): - import matplotlib.pyplot as plt - - random_array = np.random.random((1000, 3)) - df = DataFrame(random_array, columns=["A label", "B label", "C label"]) - - fig, axes = plt.subplots(1, 2) - df.plot.scatter("A label", "B label", c="C label", ax=axes[0]) - df.plot.scatter("A label", "B label", c="C label", ax=axes[1]) - plt.tight_layout() - - points = np.array([ax.get_position().get_points() for ax in fig.axes]) - axes_x_coords = points[:, :, 0] - parent_distance = axes_x_coords[1, :] - axes_x_coords[0, :] - colorbar_distance = axes_x_coords[3, :] - axes_x_coords[2, :] - assert np.isclose(parent_distance, colorbar_distance, atol=1e-7).all() - @pytest.mark.parametrize("x, y", [("x", "y"), ("y", "x"), ("y", "y")]) @pytest.mark.slow def test_plot_scatter_with_categorical_data(self, x, y): @@ -1340,17 +721,6 @@ def test_plot_scatter_with_c(self): float_array = np.array([0.0, 1.0]) df.plot.scatter(x="A", y="B", c=float_array, cmap="spring") - @pytest.mark.parametrize("cmap", [None, "Greys"]) - def test_scatter_with_c_column_name_with_colors(self, cmap): - # https://github.com/pandas-dev/pandas/issues/34316 - df = DataFrame( - [[5.1, 3.5], [4.9, 3.0], [7.0, 3.2], [6.4, 3.2], [5.9, 3.0]], - columns=["length", "width"], - ) - df["species"] = ["r", "r", "g", "g", "b"] - ax = df.plot.scatter(x=0, y=1, c="species", cmap=cmap) - assert ax.collections[0].colorbar is None - def test_plot_scatter_with_s(self): # this refers to GH 32904 df = DataFrame(np.random.random((10, 3)) * 100, columns=["a", "b", "c"]) @@ -1358,39 +728,6 @@ def test_plot_scatter_with_s(self): ax = df.plot.scatter(x="a", y="b", s="c") tm.assert_numpy_array_equal(df["c"].values, right=ax.collections[0].get_sizes()) - def test_scatter_colors(self): - df = DataFrame({"a": [1, 2, 3], "b": [1, 2, 3], "c": [1, 2, 3]}) - with pytest.raises(TypeError): - df.plot.scatter(x="a", y="b", c="c", color="green") - - default_colors = self._unpack_cycler(self.plt.rcParams) - - ax = df.plot.scatter(x="a", y="b", c="c") - tm.assert_numpy_array_equal( - ax.collections[0].get_facecolor()[0], - np.array(self.colorconverter.to_rgba(default_colors[0])), - ) - - ax = df.plot.scatter(x="a", y="b", color="white") - tm.assert_numpy_array_equal( - ax.collections[0].get_facecolor()[0], - np.array([1, 1, 1, 1], dtype=np.float64), - ) - - def test_scatter_colorbar_different_cmap(self): - # GH 33389 - import matplotlib.pyplot as plt - - df = DataFrame({"x": [1, 2, 3], "y": [1, 3, 2], "c": [1, 2, 3]}) - df["x2"] = df["x"] + 1 - - fig, ax = plt.subplots() - df.plot("x", "y", c="c", kind="scatter", cmap="cividis", ax=ax) - df.plot("x2", "y", c="c", kind="scatter", cmap="magma", ax=ax) - - assert ax.collections[0].cmap.name == "cividis" - assert ax.collections[1].cmap.name == "magma" - @pytest.mark.slow def test_plot_bar(self): df = DataFrame( @@ -1424,155 +761,6 @@ def test_plot_bar(self): ax = df.plot.barh(rot=55, fontsize=11) self._check_ticks_props(ax, yrot=55, ylabelsize=11, xlabelsize=11) - def _check_bar_alignment( - self, - df, - kind="bar", - stacked=False, - subplots=False, - align="center", - width=0.5, - position=0.5, - ): - - axes = df.plot( - kind=kind, - stacked=stacked, - subplots=subplots, - align=align, - width=width, - position=position, - grid=True, - ) - - axes = self._flatten_visible(axes) - - for ax in axes: - if kind == "bar": - axis = ax.xaxis - ax_min, ax_max = ax.get_xlim() - min_edge = min(p.get_x() for p in ax.patches) - max_edge = max(p.get_x() + p.get_width() for p in ax.patches) - elif kind == "barh": - axis = ax.yaxis - ax_min, ax_max = ax.get_ylim() - min_edge = min(p.get_y() for p in ax.patches) - max_edge = max(p.get_y() + p.get_height() for p in ax.patches) - else: - raise ValueError - - # GH 7498 - # compare margins between lim and bar edges - tm.assert_almost_equal(ax_min, min_edge - 0.25) - tm.assert_almost_equal(ax_max, max_edge + 0.25) - - p = ax.patches[0] - if kind == "bar" and (stacked is True or subplots is True): - edge = p.get_x() - center = edge + p.get_width() * position - elif kind == "bar" and stacked is False: - center = p.get_x() + p.get_width() * len(df.columns) * position - edge = p.get_x() - elif kind == "barh" and (stacked is True or subplots is True): - center = p.get_y() + p.get_height() * position - edge = p.get_y() - elif kind == "barh" and stacked is False: - center = p.get_y() + p.get_height() * len(df.columns) * position - edge = p.get_y() - else: - raise ValueError - - # Check the ticks locates on integer - assert (axis.get_ticklocs() == np.arange(len(df))).all() - - if align == "center": - # Check whether the bar locates on center - tm.assert_almost_equal(axis.get_ticklocs()[0], center) - elif align == "edge": - # Check whether the bar's edge starts from the tick - tm.assert_almost_equal(axis.get_ticklocs()[0], edge) - else: - raise ValueError - - return axes - - @pytest.mark.slow - @pytest.mark.parametrize( - "kwargs", - [ - # stacked center - dict(kind="bar", stacked=True), - dict(kind="bar", stacked=True, width=0.9), - dict(kind="barh", stacked=True), - dict(kind="barh", stacked=True, width=0.9), - # center - dict(kind="bar", stacked=False), - dict(kind="bar", stacked=False, width=0.9), - dict(kind="barh", stacked=False), - dict(kind="barh", stacked=False, width=0.9), - # subplots center - dict(kind="bar", subplots=True), - dict(kind="bar", subplots=True, width=0.9), - dict(kind="barh", subplots=True), - dict(kind="barh", subplots=True, width=0.9), - # align edge - dict(kind="bar", stacked=True, align="edge"), - dict(kind="bar", stacked=True, width=0.9, align="edge"), - dict(kind="barh", stacked=True, align="edge"), - dict(kind="barh", stacked=True, width=0.9, align="edge"), - dict(kind="bar", stacked=False, align="edge"), - dict(kind="bar", stacked=False, width=0.9, align="edge"), - dict(kind="barh", stacked=False, align="edge"), - dict(kind="barh", stacked=False, width=0.9, align="edge"), - dict(kind="bar", subplots=True, align="edge"), - dict(kind="bar", subplots=True, width=0.9, align="edge"), - dict(kind="barh", subplots=True, align="edge"), - dict(kind="barh", subplots=True, width=0.9, align="edge"), - ], - ) - def test_bar_align_multiple_columns(self, kwargs): - # GH2157 - df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5)) - self._check_bar_alignment(df, **kwargs) - - @pytest.mark.slow - @pytest.mark.parametrize( - "kwargs", - [ - dict(kind="bar", stacked=False), - dict(kind="bar", stacked=True), - dict(kind="barh", stacked=False), - dict(kind="barh", stacked=True), - dict(kind="bar", subplots=True), - dict(kind="barh", subplots=True), - ], - ) - def test_bar_align_single_column(self, kwargs): - df = DataFrame(np.random.randn(5)) - self._check_bar_alignment(df, **kwargs) - - @pytest.mark.slow - def test_bar_log_no_subplots(self): - # GH3254, GH3298 matplotlib/matplotlib#1882, #1892 - # regressions in 1.2.1 - expected = np.array([0.1, 1.0, 10.0, 100]) - - # no subplots - df = DataFrame({"A": [3] * 5, "B": list(range(1, 6))}, index=range(5)) - ax = df.plot.bar(grid=True, log=True) - tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), expected) - - @pytest.mark.slow - def test_bar_log_subplots(self): - expected = np.array([0.1, 1.0, 10.0, 100.0, 1000.0, 1e4]) - - ax = DataFrame([Series([200, 300]), Series([300, 500])]).plot.bar( - log=True, subplots=True - ) - - tm.assert_numpy_array_equal(ax[0].yaxis.get_ticklocs(), expected) - tm.assert_numpy_array_equal(ax[1].yaxis.get_ticklocs(), expected) - @pytest.mark.slow def test_boxplot(self): df = self.hist_df @@ -1655,26 +843,6 @@ def test_boxplot_return_type(self): result = df.plot.box(return_type="both") self._check_box_return_type(result, "both") - @pytest.mark.slow - def test_boxplot_subplots_return_type(self): - df = self.hist_df - - # normal style: return_type=None - result = df.plot.box(subplots=True) - assert isinstance(result, Series) - self._check_box_return_type( - result, None, expected_keys=["height", "weight", "category"] - ) - - for t in ["dict", "axes", "both"]: - returned = df.plot.box(return_type=t, subplots=True) - self._check_box_return_type( - returned, - t, - expected_keys=["height", "weight", "category"], - check_ax_title=False, - ) - @pytest.mark.slow @td.skip_if_no_scipy def test_kde_df(self): @@ -2075,352 +1243,6 @@ def test_line_label_none(self): ax = s.plot(legend=True) assert ax.get_legend().get_texts()[0].get_text() == "None" - @pytest.mark.slow - def test_line_colors(self): - from matplotlib import cm - - custom_colors = "rgcby" - df = DataFrame(np.random.randn(5, 5)) - - ax = df.plot(color=custom_colors) - self._check_colors(ax.get_lines(), linecolors=custom_colors) - - tm.close() - - ax2 = df.plot(color=custom_colors) - lines2 = ax2.get_lines() - - for l1, l2 in zip(ax.get_lines(), lines2): - assert l1.get_color() == l2.get_color() - - tm.close() - - ax = df.plot(colormap="jet") - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - self._check_colors(ax.get_lines(), linecolors=rgba_colors) - tm.close() - - ax = df.plot(colormap=cm.jet) - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - self._check_colors(ax.get_lines(), linecolors=rgba_colors) - tm.close() - - # make color a list if plotting one column frame - # handles cases like df.plot(color='DodgerBlue') - ax = df.loc[:, [0]].plot(color="DodgerBlue") - self._check_colors(ax.lines, linecolors=["DodgerBlue"]) - - ax = df.plot(color="red") - self._check_colors(ax.get_lines(), linecolors=["red"] * 5) - tm.close() - - # GH 10299 - custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"] - ax = df.plot(color=custom_colors) - self._check_colors(ax.get_lines(), linecolors=custom_colors) - tm.close() - - @pytest.mark.slow - def test_dont_modify_colors(self): - colors = ["r", "g", "b"] - DataFrame(np.random.rand(10, 2)).plot(color=colors) - assert len(colors) == 3 - - @pytest.mark.slow - def test_line_colors_and_styles_subplots(self): - # GH 9894 - from matplotlib import cm - - default_colors = self._unpack_cycler(self.plt.rcParams) - - df = DataFrame(np.random.randn(5, 5)) - - axes = df.plot(subplots=True) - for ax, c in zip(axes, list(default_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - # single color char - axes = df.plot(subplots=True, color="k") - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["k"]) - tm.close() - - # single color str - axes = df.plot(subplots=True, color="green") - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["green"]) - tm.close() - - custom_colors = "rgcby" - axes = df.plot(color=custom_colors, subplots=True) - for ax, c in zip(axes, list(custom_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - axes = df.plot(color=list(custom_colors), subplots=True) - for ax, c in zip(axes, list(custom_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - # GH 10299 - custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"] - axes = df.plot(color=custom_colors, subplots=True) - for ax, c in zip(axes, list(custom_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - for cmap in ["jet", cm.jet]: - axes = df.plot(colormap=cmap, subplots=True) - for ax, c in zip(axes, rgba_colors): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - # make color a list if plotting one column frame - # handles cases like df.plot(color='DodgerBlue') - axes = df.loc[:, [0]].plot(color="DodgerBlue", subplots=True) - self._check_colors(axes[0].lines, linecolors=["DodgerBlue"]) - - # single character style - axes = df.plot(style="r", subplots=True) - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["r"]) - tm.close() - - # list of styles - styles = list("rgcby") - axes = df.plot(style=styles, subplots=True) - for ax, c in zip(axes, styles): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - @pytest.mark.slow - def test_area_colors(self): - from matplotlib import cm - from matplotlib.collections import PolyCollection - - custom_colors = "rgcby" - df = DataFrame(np.random.rand(5, 5)) - - ax = df.plot.area(color=custom_colors) - self._check_colors(ax.get_lines(), linecolors=custom_colors) - poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] - self._check_colors(poly, facecolors=custom_colors) - - handles, labels = ax.get_legend_handles_labels() - self._check_colors(handles, facecolors=custom_colors) - - for h in handles: - assert h.get_alpha() is None - tm.close() - - ax = df.plot.area(colormap="jet") - jet_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - self._check_colors(ax.get_lines(), linecolors=jet_colors) - poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] - self._check_colors(poly, facecolors=jet_colors) - - handles, labels = ax.get_legend_handles_labels() - self._check_colors(handles, facecolors=jet_colors) - for h in handles: - assert h.get_alpha() is None - tm.close() - - # When stacked=False, alpha is set to 0.5 - ax = df.plot.area(colormap=cm.jet, stacked=False) - self._check_colors(ax.get_lines(), linecolors=jet_colors) - poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] - jet_with_alpha = [(c[0], c[1], c[2], 0.5) for c in jet_colors] - self._check_colors(poly, facecolors=jet_with_alpha) - - handles, labels = ax.get_legend_handles_labels() - linecolors = jet_with_alpha - self._check_colors(handles[: len(jet_colors)], linecolors=linecolors) - for h in handles: - assert h.get_alpha() == 0.5 - - @pytest.mark.slow - def test_hist_colors(self): - default_colors = self._unpack_cycler(self.plt.rcParams) - - df = DataFrame(np.random.randn(5, 5)) - ax = df.plot.hist() - self._check_colors(ax.patches[::10], facecolors=default_colors[:5]) - tm.close() - - custom_colors = "rgcby" - ax = df.plot.hist(color=custom_colors) - self._check_colors(ax.patches[::10], facecolors=custom_colors) - tm.close() - - from matplotlib import cm - - # Test str -> colormap functionality - ax = df.plot.hist(colormap="jet") - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] - self._check_colors(ax.patches[::10], facecolors=rgba_colors) - tm.close() - - # Test colormap functionality - ax = df.plot.hist(colormap=cm.jet) - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] - self._check_colors(ax.patches[::10], facecolors=rgba_colors) - tm.close() - - ax = df.loc[:, [0]].plot.hist(color="DodgerBlue") - self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"]) - - ax = df.plot(kind="hist", color="green") - self._check_colors(ax.patches[::10], facecolors=["green"] * 5) - tm.close() - - @pytest.mark.slow - @td.skip_if_no_scipy - def test_kde_colors(self): - from matplotlib import cm - - custom_colors = "rgcby" - df = DataFrame(np.random.rand(5, 5)) - - ax = df.plot.kde(color=custom_colors) - self._check_colors(ax.get_lines(), linecolors=custom_colors) - tm.close() - - ax = df.plot.kde(colormap="jet") - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - self._check_colors(ax.get_lines(), linecolors=rgba_colors) - tm.close() - - ax = df.plot.kde(colormap=cm.jet) - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - self._check_colors(ax.get_lines(), linecolors=rgba_colors) - - @pytest.mark.slow - @td.skip_if_no_scipy - def test_kde_colors_and_styles_subplots(self): - from matplotlib import cm - - default_colors = self._unpack_cycler(self.plt.rcParams) - - df = DataFrame(np.random.randn(5, 5)) - - axes = df.plot(kind="kde", subplots=True) - for ax, c in zip(axes, list(default_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - # single color char - axes = df.plot(kind="kde", color="k", subplots=True) - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["k"]) - tm.close() - - # single color str - axes = df.plot(kind="kde", color="red", subplots=True) - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["red"]) - tm.close() - - custom_colors = "rgcby" - axes = df.plot(kind="kde", color=custom_colors, subplots=True) - for ax, c in zip(axes, list(custom_colors)): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] - for cmap in ["jet", cm.jet]: - axes = df.plot(kind="kde", colormap=cmap, subplots=True) - for ax, c in zip(axes, rgba_colors): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - # make color a list if plotting one column frame - # handles cases like df.plot(color='DodgerBlue') - axes = df.loc[:, [0]].plot(kind="kde", color="DodgerBlue", subplots=True) - self._check_colors(axes[0].lines, linecolors=["DodgerBlue"]) - - # single character style - axes = df.plot(kind="kde", style="r", subplots=True) - for ax in axes: - self._check_colors(ax.get_lines(), linecolors=["r"]) - tm.close() - - # list of styles - styles = list("rgcby") - axes = df.plot(kind="kde", style=styles, subplots=True) - for ax, c in zip(axes, styles): - self._check_colors(ax.get_lines(), linecolors=[c]) - tm.close() - - @pytest.mark.slow - def test_boxplot_colors(self): - def _check_colors(bp, box_c, whiskers_c, medians_c, caps_c="k", fliers_c=None): - # TODO: outside this func? - if fliers_c is None: - fliers_c = "k" - self._check_colors(bp["boxes"], linecolors=[box_c] * len(bp["boxes"])) - self._check_colors( - bp["whiskers"], linecolors=[whiskers_c] * len(bp["whiskers"]) - ) - self._check_colors( - bp["medians"], linecolors=[medians_c] * len(bp["medians"]) - ) - self._check_colors(bp["fliers"], linecolors=[fliers_c] * len(bp["fliers"])) - self._check_colors(bp["caps"], linecolors=[caps_c] * len(bp["caps"])) - - default_colors = self._unpack_cycler(self.plt.rcParams) - - df = DataFrame(np.random.randn(5, 5)) - bp = df.plot.box(return_type="dict") - _check_colors(bp, default_colors[0], default_colors[0], default_colors[2]) - tm.close() - - dict_colors = dict( - boxes="#572923", whiskers="#982042", medians="#804823", caps="#123456" - ) - bp = df.plot.box(color=dict_colors, sym="r+", return_type="dict") - _check_colors( - bp, - dict_colors["boxes"], - dict_colors["whiskers"], - dict_colors["medians"], - dict_colors["caps"], - "r", - ) - tm.close() - - # partial colors - dict_colors = dict(whiskers="c", medians="m") - bp = df.plot.box(color=dict_colors, return_type="dict") - _check_colors(bp, default_colors[0], "c", "m") - tm.close() - - from matplotlib import cm - - # Test str -> colormap functionality - bp = df.plot.box(colormap="jet", return_type="dict") - jet_colors = [cm.jet(n) for n in np.linspace(0, 1, 3)] - _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2]) - tm.close() - - # Test colormap functionality - bp = df.plot.box(colormap=cm.jet, return_type="dict") - _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2]) - tm.close() - - # string color is applied to all artists except fliers - bp = df.plot.box(color="DodgerBlue", return_type="dict") - _check_colors(bp, "DodgerBlue", "DodgerBlue", "DodgerBlue", "DodgerBlue") - - # tuple is also applied to all artists except fliers - bp = df.plot.box(color=(0, 1, 0), sym="#123456", return_type="dict") - _check_colors(bp, (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), "#123456") - - with pytest.raises(ValueError): - # Color contains invalid key results in ValueError - df.plot.box(color=dict(boxes="red", xxxx="blue")) - @pytest.mark.parametrize( "props, expected", [ @@ -2438,19 +1260,6 @@ def test_specified_props_kwd_plot_box(self, props, expected): assert result[expected][0].get_color() == "C1" - def test_default_color_cycle(self): - import cycler - import matplotlib.pyplot as plt - - colors = list("rgbk") - plt.rcParams["axes.prop_cycle"] = cycler.cycler("color", colors) - - df = DataFrame(np.random.randn(5, 3)) - ax = df.plot() - - expected = self._unpack_cycler(plt.rcParams)[:3] - self._check_colors(ax.get_lines(), linecolors=expected) - def test_unordered_ts(self): df = DataFrame( np.array([3.0, 2.0, 1.0]), @@ -2592,19 +1401,6 @@ def test_hexbin_cmap(self, kwargs, expected): ax = df.plot.hexbin(x="A", y="B", **kwargs) assert ax.collections[0].cmap.name == expected - @pytest.mark.slow - def test_no_color_bar(self): - df = self.hexbin_df - ax = df.plot.hexbin(x="A", y="B", colorbar=None) - assert ax.collections[0].colorbar is None - - @pytest.mark.slow - def test_mixing_cmap_and_colormap_raises(self): - df = self.hexbin_df - msg = "Only specify one of `cmap` and `colormap`" - with pytest.raises(TypeError, match=msg): - df.plot.hexbin(x="A", y="B", cmap="YlGn", colormap="BuGn") - @pytest.mark.slow def test_pie_df(self): df = DataFrame( @@ -3047,53 +1843,6 @@ def test_memory_leak(self): # need to actually access something to get an error results[key].lines - @pytest.mark.slow - def test_df_subplots_patterns_minorticks(self): - # GH 10657 - import matplotlib.pyplot as plt - - df = DataFrame( - np.random.randn(10, 2), - index=date_range("1/1/2000", periods=10), - columns=list("AB"), - ) - - # shared subplots - fig, axes = plt.subplots(2, 1, sharex=True) - axes = df.plot(subplots=True, ax=axes) - for ax in axes: - assert len(ax.lines) == 1 - self._check_visible(ax.get_yticklabels(), visible=True) - # xaxis of 1st ax must be hidden - self._check_visible(axes[0].get_xticklabels(), visible=False) - self._check_visible(axes[0].get_xticklabels(minor=True), visible=False) - self._check_visible(axes[1].get_xticklabels(), visible=True) - self._check_visible(axes[1].get_xticklabels(minor=True), visible=True) - tm.close() - - fig, axes = plt.subplots(2, 1) - with tm.assert_produces_warning(UserWarning): - axes = df.plot(subplots=True, ax=axes, sharex=True) - for ax in axes: - assert len(ax.lines) == 1 - self._check_visible(ax.get_yticklabels(), visible=True) - # xaxis of 1st ax must be hidden - self._check_visible(axes[0].get_xticklabels(), visible=False) - self._check_visible(axes[0].get_xticklabels(minor=True), visible=False) - self._check_visible(axes[1].get_xticklabels(), visible=True) - self._check_visible(axes[1].get_xticklabels(minor=True), visible=True) - tm.close() - - # not shared - fig, axes = plt.subplots(2, 1) - axes = df.plot(subplots=True, ax=axes) - for ax in axes: - assert len(ax.lines) == 1 - self._check_visible(ax.get_yticklabels(), visible=True) - self._check_visible(ax.get_xticklabels(), visible=True) - self._check_visible(ax.get_xticklabels(minor=True), visible=True) - tm.close() - @pytest.mark.slow def test_df_gridspec_patterns(self): # GH 10819 @@ -3219,12 +1968,6 @@ def test_df_grid_settings(self): kws={"x": "a", "y": "b"}, ) - def test_invalid_colormap(self): - df = DataFrame(np.random.randn(3, 2), columns=["A", "B"]) - - with pytest.raises(ValueError): - df.plot(colormap="invalid_colormap") - def test_plain_axes(self): # supplied ax itself is a SubplotAxes, but figure contains also @@ -3256,22 +1999,6 @@ def test_plain_axes(self): Series(np.random.rand(10)).plot(ax=ax) Series(np.random.rand(10)).plot(ax=iax) - def test_passed_bar_colors(self): - import matplotlib as mpl - - color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)] - colormap = mpl.colors.ListedColormap(color_tuples) - barplot = DataFrame([[1, 2, 3]]).plot(kind="bar", cmap=colormap) - assert color_tuples == [c.get_facecolor() for c in barplot.patches] - - def test_rcParams_bar_colors(self): - import matplotlib as mpl - - color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)] - with mpl.rc_context(rc={"axes.prop_cycle": mpl.cycler("color", color_tuples)}): - barplot = DataFrame([[1, 2, 3]]).plot(kind="bar") - assert color_tuples == [c.get_facecolor() for c in barplot.patches] - @pytest.mark.parametrize("method", ["line", "barh", "bar"]) def test_secondary_axis_font_size(self, method): # GH: 12565 @@ -3360,22 +2087,6 @@ def test_xlim_plot_line_correctly_in_mixed_plot_type(self): xticklabels = [t.get_text() for t in ax.get_xticklabels()] assert xticklabels == indexes - def test_subplots_sharex_false(self): - # test when sharex is set to False, two plots should have different - # labels, GH 25160 - df = DataFrame(np.random.rand(10, 2)) - df.iloc[5:, 1] = np.nan - df.iloc[:5, 0] = np.nan - - figs, axs = self.plt.subplots(2, 1) - df.plot.line(ax=axs, subplots=True, sharex=False) - - expected_ax1 = np.arange(4.5, 10, 0.5) - expected_ax2 = np.arange(-0.5, 5, 0.5) - - tm.assert_numpy_array_equal(axs[0].get_xticks(), expected_ax1) - tm.assert_numpy_array_equal(axs[1].get_xticks(), expected_ax2) - def test_plot_no_rows(self): # GH 27758 df = DataFrame(columns=["foo"], dtype=int) @@ -3419,16 +2130,6 @@ def test_missing_markers_legend_using_style(self): self._check_legend_labels(ax, labels=["A", "B", "C"]) self._check_legend_marker(ax, expected_markers=[".", ".", "."]) - def test_colors_of_columns_with_same_name(self): - # ISSUE 11136 -> https://github.com/pandas-dev/pandas/issues/11136 - # Creating a DataFrame with duplicate column labels and testing colors of them. - df = DataFrame({"b": [0, 1, 0], "a": [1, 2, 3]}) - df1 = DataFrame({"a": [2, 4, 6]}) - df_concat = pd.concat([df, df1], axis=1) - result = df_concat.plot() - for legend, line in zip(result.get_legend().legendHandles, result.lines): - assert legend.get_color() == line.get_color() - @pytest.mark.parametrize( "index_name, old_label, new_label", [ @@ -3478,34 +2179,6 @@ def test_xlabel_ylabel_dataframe_plane_plot(self, kind, xlabel, ylabel): assert ax.get_xlabel() == (xcol if xlabel is None else xlabel) assert ax.get_ylabel() == (ycol if ylabel is None else ylabel) - @pytest.mark.parametrize( - "index_name, old_label, new_label", - [ - (None, "", "new"), - ("old", "old", "new"), - (None, "", ""), - (None, "", 1), - (None, "", [1, 2]), - ], - ) - @pytest.mark.parametrize("kind", ["line", "area", "bar"]) - def test_xlabel_ylabel_dataframe_subplots( - self, kind, index_name, old_label, new_label - ): - # GH 9093 - df = DataFrame([[1, 2], [2, 5]], columns=["Type A", "Type B"]) - df.index.name = index_name - - # default is the ylabel is not shown and xlabel is index name - axes = df.plot(kind=kind, subplots=True) - assert all(ax.get_ylabel() == "" for ax in axes) - assert all(ax.get_xlabel() == old_label for ax in axes) - - # old xlabel will be overriden and assigned ylabel will be used as ylabel - axes = df.plot(kind=kind, ylabel=new_label, xlabel=new_label, subplots=True) - assert all(ax.get_ylabel() == str(new_label) for ax in axes) - assert all(ax.get_xlabel() == str(new_label) for ax in axes) - def _generate_4_axes_via_gridspec(): import matplotlib as mpl diff --git a/pandas/tests/plotting/frame/test_frame_color.py b/pandas/tests/plotting/frame/test_frame_color.py new file mode 100644 index 0000000000000..d9fe7363a15ad --- /dev/null +++ b/pandas/tests/plotting/frame/test_frame_color.py @@ -0,0 +1,655 @@ +""" Test cases for DataFrame.plot """ + +import warnings + +import numpy as np +import pytest + +import pandas.util._test_decorators as td + +import pandas as pd +from pandas import DataFrame +import pandas._testing as tm +from pandas.tests.plotting.common import TestPlotBase, _check_plot_works + + +@td.skip_if_no_mpl +class TestDataFrameColor(TestPlotBase): + def setup_method(self, method): + TestPlotBase.setup_method(self, method) + import matplotlib as mpl + + mpl.rcdefaults() + + self.tdf = tm.makeTimeDataFrame() + self.hexbin_df = DataFrame( + { + "A": np.random.uniform(size=20), + "B": np.random.uniform(size=20), + "C": np.arange(20) + np.random.uniform(size=20), + } + ) + + def test_mpl2_color_cycle_str(self): + # GH 15516 + df = DataFrame(np.random.randn(10, 3), columns=["a", "b", "c"]) + colors = ["C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9"] + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always", "MatplotlibDeprecationWarning") + + for color in colors: + _check_plot_works(df.plot, color=color) + + # if warning is raised, check that it is the exact problematic one + # GH 36972 + if w: + match = "Support for uppercase single-letter colors is deprecated" + warning_message = str(w[0].message) + msg = "MatplotlibDeprecationWarning related to CN colors was raised" + assert match not in warning_message, msg + + def test_color_single_series_list(self): + # GH 3486 + df = DataFrame({"A": [1, 2, 3]}) + _check_plot_works(df.plot, color=["red"]) + + @pytest.mark.parametrize("color", [(1, 0, 0), (1, 0, 0, 0.5)]) + def test_rgb_tuple_color(self, color): + # GH 16695 + df = DataFrame({"x": [1, 2], "y": [3, 4]}) + _check_plot_works(df.plot, x="x", y="y", color=color) + + def test_color_empty_string(self): + df = DataFrame(np.random.randn(10, 2)) + with pytest.raises(ValueError): + df.plot(color="") + + def test_color_and_style_arguments(self): + df = DataFrame({"x": [1, 2], "y": [3, 4]}) + # passing both 'color' and 'style' arguments should be allowed + # if there is no color symbol in the style strings: + ax = df.plot(color=["red", "black"], style=["-", "--"]) + # check that the linestyles are correctly set: + linestyle = [line.get_linestyle() for line in ax.lines] + assert linestyle == ["-", "--"] + # check that the colors are correctly set: + color = [line.get_color() for line in ax.lines] + assert color == ["red", "black"] + # passing both 'color' and 'style' arguments should not be allowed + # if there is a color symbol in the style strings: + with pytest.raises(ValueError): + df.plot(color=["red", "black"], style=["k-", "r--"]) + + @pytest.mark.parametrize( + "color, expected", + [ + ("green", ["green"] * 4), + (["yellow", "red", "green", "blue"], ["yellow", "red", "green", "blue"]), + ], + ) + def test_color_and_marker(self, color, expected): + # GH 21003 + df = DataFrame(np.random.random((7, 4))) + ax = df.plot(color=color, style="d--") + # check colors + result = [i.get_color() for i in ax.lines] + assert result == expected + # check markers and linestyles + assert all(i.get_linestyle() == "--" for i in ax.lines) + assert all(i.get_marker() == "d" for i in ax.lines) + + @pytest.mark.slow + def test_bar_colors(self): + import matplotlib.pyplot as plt + + default_colors = self._unpack_cycler(plt.rcParams) + + df = DataFrame(np.random.randn(5, 5)) + ax = df.plot.bar() + self._check_colors(ax.patches[::5], facecolors=default_colors[:5]) + tm.close() + + custom_colors = "rgcby" + ax = df.plot.bar(color=custom_colors) + self._check_colors(ax.patches[::5], facecolors=custom_colors) + tm.close() + + from matplotlib import cm + + # Test str -> colormap functionality + ax = df.plot.bar(colormap="jet") + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] + self._check_colors(ax.patches[::5], facecolors=rgba_colors) + tm.close() + + # Test colormap functionality + ax = df.plot.bar(colormap=cm.jet) + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] + self._check_colors(ax.patches[::5], facecolors=rgba_colors) + tm.close() + + ax = df.loc[:, [0]].plot.bar(color="DodgerBlue") + self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"]) + tm.close() + + ax = df.plot(kind="bar", color="green") + self._check_colors(ax.patches[::5], facecolors=["green"] * 5) + tm.close() + + def test_bar_user_colors(self): + df = DataFrame( + {"A": range(4), "B": range(1, 5), "color": ["red", "blue", "blue", "red"]} + ) + # This should *only* work when `y` is specified, else + # we use one color per column + ax = df.plot.bar(y="A", color=df["color"]) + result = [p.get_facecolor() for p in ax.patches] + expected = [ + (1.0, 0.0, 0.0, 1.0), + (0.0, 0.0, 1.0, 1.0), + (0.0, 0.0, 1.0, 1.0), + (1.0, 0.0, 0.0, 1.0), + ] + assert result == expected + + @pytest.mark.slow + def test_if_scatterplot_colorbar_affects_xaxis_visibility(self): + # addressing issue #10611, to ensure colobar does not + # interfere with x-axis label and ticklabels with + # ipython inline backend. + random_array = np.random.random((1000, 3)) + df = DataFrame(random_array, columns=["A label", "B label", "C label"]) + + ax1 = df.plot.scatter(x="A label", y="B label") + ax2 = df.plot.scatter(x="A label", y="B label", c="C label") + + vis1 = [vis.get_visible() for vis in ax1.xaxis.get_minorticklabels()] + vis2 = [vis.get_visible() for vis in ax2.xaxis.get_minorticklabels()] + assert vis1 == vis2 + + vis1 = [vis.get_visible() for vis in ax1.xaxis.get_majorticklabels()] + vis2 = [vis.get_visible() for vis in ax2.xaxis.get_majorticklabels()] + assert vis1 == vis2 + + assert ( + ax1.xaxis.get_label().get_visible() == ax2.xaxis.get_label().get_visible() + ) + + @pytest.mark.slow + def test_if_hexbin_xaxis_label_is_visible(self): + # addressing issue #10678, to ensure colobar does not + # interfere with x-axis label and ticklabels with + # ipython inline backend. + random_array = np.random.random((1000, 3)) + df = DataFrame(random_array, columns=["A label", "B label", "C label"]) + + ax = df.plot.hexbin("A label", "B label", gridsize=12) + assert all(vis.get_visible() for vis in ax.xaxis.get_minorticklabels()) + assert all(vis.get_visible() for vis in ax.xaxis.get_majorticklabels()) + assert ax.xaxis.get_label().get_visible() + + @pytest.mark.slow + def test_if_scatterplot_colorbars_are_next_to_parent_axes(self): + import matplotlib.pyplot as plt + + random_array = np.random.random((1000, 3)) + df = DataFrame(random_array, columns=["A label", "B label", "C label"]) + + fig, axes = plt.subplots(1, 2) + df.plot.scatter("A label", "B label", c="C label", ax=axes[0]) + df.plot.scatter("A label", "B label", c="C label", ax=axes[1]) + plt.tight_layout() + + points = np.array([ax.get_position().get_points() for ax in fig.axes]) + axes_x_coords = points[:, :, 0] + parent_distance = axes_x_coords[1, :] - axes_x_coords[0, :] + colorbar_distance = axes_x_coords[3, :] - axes_x_coords[2, :] + assert np.isclose(parent_distance, colorbar_distance, atol=1e-7).all() + + @pytest.mark.parametrize("cmap", [None, "Greys"]) + def test_scatter_with_c_column_name_with_colors(self, cmap): + # https://github.com/pandas-dev/pandas/issues/34316 + df = DataFrame( + [[5.1, 3.5], [4.9, 3.0], [7.0, 3.2], [6.4, 3.2], [5.9, 3.0]], + columns=["length", "width"], + ) + df["species"] = ["r", "r", "g", "g", "b"] + ax = df.plot.scatter(x=0, y=1, c="species", cmap=cmap) + assert ax.collections[0].colorbar is None + + def test_scatter_colors(self): + df = DataFrame({"a": [1, 2, 3], "b": [1, 2, 3], "c": [1, 2, 3]}) + with pytest.raises(TypeError): + df.plot.scatter(x="a", y="b", c="c", color="green") + + default_colors = self._unpack_cycler(self.plt.rcParams) + + ax = df.plot.scatter(x="a", y="b", c="c") + tm.assert_numpy_array_equal( + ax.collections[0].get_facecolor()[0], + np.array(self.colorconverter.to_rgba(default_colors[0])), + ) + + ax = df.plot.scatter(x="a", y="b", color="white") + tm.assert_numpy_array_equal( + ax.collections[0].get_facecolor()[0], + np.array([1, 1, 1, 1], dtype=np.float64), + ) + + def test_scatter_colorbar_different_cmap(self): + # GH 33389 + import matplotlib.pyplot as plt + + df = DataFrame({"x": [1, 2, 3], "y": [1, 3, 2], "c": [1, 2, 3]}) + df["x2"] = df["x"] + 1 + + fig, ax = plt.subplots() + df.plot("x", "y", c="c", kind="scatter", cmap="cividis", ax=ax) + df.plot("x2", "y", c="c", kind="scatter", cmap="magma", ax=ax) + + assert ax.collections[0].cmap.name == "cividis" + assert ax.collections[1].cmap.name == "magma" + + @pytest.mark.slow + def test_line_colors(self): + from matplotlib import cm + + custom_colors = "rgcby" + df = DataFrame(np.random.randn(5, 5)) + + ax = df.plot(color=custom_colors) + self._check_colors(ax.get_lines(), linecolors=custom_colors) + + tm.close() + + ax2 = df.plot(color=custom_colors) + lines2 = ax2.get_lines() + + for l1, l2 in zip(ax.get_lines(), lines2): + assert l1.get_color() == l2.get_color() + + tm.close() + + ax = df.plot(colormap="jet") + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + self._check_colors(ax.get_lines(), linecolors=rgba_colors) + tm.close() + + ax = df.plot(colormap=cm.jet) + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + self._check_colors(ax.get_lines(), linecolors=rgba_colors) + tm.close() + + # make color a list if plotting one column frame + # handles cases like df.plot(color='DodgerBlue') + ax = df.loc[:, [0]].plot(color="DodgerBlue") + self._check_colors(ax.lines, linecolors=["DodgerBlue"]) + + ax = df.plot(color="red") + self._check_colors(ax.get_lines(), linecolors=["red"] * 5) + tm.close() + + # GH 10299 + custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"] + ax = df.plot(color=custom_colors) + self._check_colors(ax.get_lines(), linecolors=custom_colors) + tm.close() + + @pytest.mark.slow + def test_dont_modify_colors(self): + colors = ["r", "g", "b"] + DataFrame(np.random.rand(10, 2)).plot(color=colors) + assert len(colors) == 3 + + @pytest.mark.slow + def test_line_colors_and_styles_subplots(self): + # GH 9894 + from matplotlib import cm + + default_colors = self._unpack_cycler(self.plt.rcParams) + + df = DataFrame(np.random.randn(5, 5)) + + axes = df.plot(subplots=True) + for ax, c in zip(axes, list(default_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + # single color char + axes = df.plot(subplots=True, color="k") + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["k"]) + tm.close() + + # single color str + axes = df.plot(subplots=True, color="green") + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["green"]) + tm.close() + + custom_colors = "rgcby" + axes = df.plot(color=custom_colors, subplots=True) + for ax, c in zip(axes, list(custom_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + axes = df.plot(color=list(custom_colors), subplots=True) + for ax, c in zip(axes, list(custom_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + # GH 10299 + custom_colors = ["#FF0000", "#0000FF", "#FFFF00", "#000000", "#FFFFFF"] + axes = df.plot(color=custom_colors, subplots=True) + for ax, c in zip(axes, list(custom_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + for cmap in ["jet", cm.jet]: + axes = df.plot(colormap=cmap, subplots=True) + for ax, c in zip(axes, rgba_colors): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + # make color a list if plotting one column frame + # handles cases like df.plot(color='DodgerBlue') + axes = df.loc[:, [0]].plot(color="DodgerBlue", subplots=True) + self._check_colors(axes[0].lines, linecolors=["DodgerBlue"]) + + # single character style + axes = df.plot(style="r", subplots=True) + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["r"]) + tm.close() + + # list of styles + styles = list("rgcby") + axes = df.plot(style=styles, subplots=True) + for ax, c in zip(axes, styles): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + @pytest.mark.slow + def test_area_colors(self): + from matplotlib import cm + from matplotlib.collections import PolyCollection + + custom_colors = "rgcby" + df = DataFrame(np.random.rand(5, 5)) + + ax = df.plot.area(color=custom_colors) + self._check_colors(ax.get_lines(), linecolors=custom_colors) + poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] + self._check_colors(poly, facecolors=custom_colors) + + handles, labels = ax.get_legend_handles_labels() + self._check_colors(handles, facecolors=custom_colors) + + for h in handles: + assert h.get_alpha() is None + tm.close() + + ax = df.plot.area(colormap="jet") + jet_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + self._check_colors(ax.get_lines(), linecolors=jet_colors) + poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] + self._check_colors(poly, facecolors=jet_colors) + + handles, labels = ax.get_legend_handles_labels() + self._check_colors(handles, facecolors=jet_colors) + for h in handles: + assert h.get_alpha() is None + tm.close() + + # When stacked=False, alpha is set to 0.5 + ax = df.plot.area(colormap=cm.jet, stacked=False) + self._check_colors(ax.get_lines(), linecolors=jet_colors) + poly = [o for o in ax.get_children() if isinstance(o, PolyCollection)] + jet_with_alpha = [(c[0], c[1], c[2], 0.5) for c in jet_colors] + self._check_colors(poly, facecolors=jet_with_alpha) + + handles, labels = ax.get_legend_handles_labels() + linecolors = jet_with_alpha + self._check_colors(handles[: len(jet_colors)], linecolors=linecolors) + for h in handles: + assert h.get_alpha() == 0.5 + + @pytest.mark.slow + def test_hist_colors(self): + default_colors = self._unpack_cycler(self.plt.rcParams) + + df = DataFrame(np.random.randn(5, 5)) + ax = df.plot.hist() + self._check_colors(ax.patches[::10], facecolors=default_colors[:5]) + tm.close() + + custom_colors = "rgcby" + ax = df.plot.hist(color=custom_colors) + self._check_colors(ax.patches[::10], facecolors=custom_colors) + tm.close() + + from matplotlib import cm + + # Test str -> colormap functionality + ax = df.plot.hist(colormap="jet") + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] + self._check_colors(ax.patches[::10], facecolors=rgba_colors) + tm.close() + + # Test colormap functionality + ax = df.plot.hist(colormap=cm.jet) + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, 5)] + self._check_colors(ax.patches[::10], facecolors=rgba_colors) + tm.close() + + ax = df.loc[:, [0]].plot.hist(color="DodgerBlue") + self._check_colors([ax.patches[0]], facecolors=["DodgerBlue"]) + + ax = df.plot(kind="hist", color="green") + self._check_colors(ax.patches[::10], facecolors=["green"] * 5) + tm.close() + + @pytest.mark.slow + @td.skip_if_no_scipy + def test_kde_colors(self): + from matplotlib import cm + + custom_colors = "rgcby" + df = DataFrame(np.random.rand(5, 5)) + + ax = df.plot.kde(color=custom_colors) + self._check_colors(ax.get_lines(), linecolors=custom_colors) + tm.close() + + ax = df.plot.kde(colormap="jet") + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + self._check_colors(ax.get_lines(), linecolors=rgba_colors) + tm.close() + + ax = df.plot.kde(colormap=cm.jet) + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + self._check_colors(ax.get_lines(), linecolors=rgba_colors) + + @pytest.mark.slow + @td.skip_if_no_scipy + def test_kde_colors_and_styles_subplots(self): + from matplotlib import cm + + default_colors = self._unpack_cycler(self.plt.rcParams) + + df = DataFrame(np.random.randn(5, 5)) + + axes = df.plot(kind="kde", subplots=True) + for ax, c in zip(axes, list(default_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + # single color char + axes = df.plot(kind="kde", color="k", subplots=True) + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["k"]) + tm.close() + + # single color str + axes = df.plot(kind="kde", color="red", subplots=True) + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["red"]) + tm.close() + + custom_colors = "rgcby" + axes = df.plot(kind="kde", color=custom_colors, subplots=True) + for ax, c in zip(axes, list(custom_colors)): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + rgba_colors = [cm.jet(n) for n in np.linspace(0, 1, len(df))] + for cmap in ["jet", cm.jet]: + axes = df.plot(kind="kde", colormap=cmap, subplots=True) + for ax, c in zip(axes, rgba_colors): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + # make color a list if plotting one column frame + # handles cases like df.plot(color='DodgerBlue') + axes = df.loc[:, [0]].plot(kind="kde", color="DodgerBlue", subplots=True) + self._check_colors(axes[0].lines, linecolors=["DodgerBlue"]) + + # single character style + axes = df.plot(kind="kde", style="r", subplots=True) + for ax in axes: + self._check_colors(ax.get_lines(), linecolors=["r"]) + tm.close() + + # list of styles + styles = list("rgcby") + axes = df.plot(kind="kde", style=styles, subplots=True) + for ax, c in zip(axes, styles): + self._check_colors(ax.get_lines(), linecolors=[c]) + tm.close() + + @pytest.mark.slow + def test_boxplot_colors(self): + def _check_colors(bp, box_c, whiskers_c, medians_c, caps_c="k", fliers_c=None): + # TODO: outside this func? + if fliers_c is None: + fliers_c = "k" + self._check_colors(bp["boxes"], linecolors=[box_c] * len(bp["boxes"])) + self._check_colors( + bp["whiskers"], linecolors=[whiskers_c] * len(bp["whiskers"]) + ) + self._check_colors( + bp["medians"], linecolors=[medians_c] * len(bp["medians"]) + ) + self._check_colors(bp["fliers"], linecolors=[fliers_c] * len(bp["fliers"])) + self._check_colors(bp["caps"], linecolors=[caps_c] * len(bp["caps"])) + + default_colors = self._unpack_cycler(self.plt.rcParams) + + df = DataFrame(np.random.randn(5, 5)) + bp = df.plot.box(return_type="dict") + _check_colors(bp, default_colors[0], default_colors[0], default_colors[2]) + tm.close() + + dict_colors = dict( + boxes="#572923", whiskers="#982042", medians="#804823", caps="#123456" + ) + bp = df.plot.box(color=dict_colors, sym="r+", return_type="dict") + _check_colors( + bp, + dict_colors["boxes"], + dict_colors["whiskers"], + dict_colors["medians"], + dict_colors["caps"], + "r", + ) + tm.close() + + # partial colors + dict_colors = dict(whiskers="c", medians="m") + bp = df.plot.box(color=dict_colors, return_type="dict") + _check_colors(bp, default_colors[0], "c", "m") + tm.close() + + from matplotlib import cm + + # Test str -> colormap functionality + bp = df.plot.box(colormap="jet", return_type="dict") + jet_colors = [cm.jet(n) for n in np.linspace(0, 1, 3)] + _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2]) + tm.close() + + # Test colormap functionality + bp = df.plot.box(colormap=cm.jet, return_type="dict") + _check_colors(bp, jet_colors[0], jet_colors[0], jet_colors[2]) + tm.close() + + # string color is applied to all artists except fliers + bp = df.plot.box(color="DodgerBlue", return_type="dict") + _check_colors(bp, "DodgerBlue", "DodgerBlue", "DodgerBlue", "DodgerBlue") + + # tuple is also applied to all artists except fliers + bp = df.plot.box(color=(0, 1, 0), sym="#123456", return_type="dict") + _check_colors(bp, (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), "#123456") + + with pytest.raises(ValueError): + # Color contains invalid key results in ValueError + df.plot.box(color=dict(boxes="red", xxxx="blue")) + + def test_default_color_cycle(self): + import cycler + import matplotlib.pyplot as plt + + colors = list("rgbk") + plt.rcParams["axes.prop_cycle"] = cycler.cycler("color", colors) + + df = DataFrame(np.random.randn(5, 3)) + ax = df.plot() + + expected = self._unpack_cycler(plt.rcParams)[:3] + self._check_colors(ax.get_lines(), linecolors=expected) + + @pytest.mark.slow + def test_no_color_bar(self): + df = self.hexbin_df + ax = df.plot.hexbin(x="A", y="B", colorbar=None) + assert ax.collections[0].colorbar is None + + @pytest.mark.slow + def test_mixing_cmap_and_colormap_raises(self): + df = self.hexbin_df + msg = "Only specify one of `cmap` and `colormap`" + with pytest.raises(TypeError, match=msg): + df.plot.hexbin(x="A", y="B", cmap="YlGn", colormap="BuGn") + + def test_passed_bar_colors(self): + import matplotlib as mpl + + color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)] + colormap = mpl.colors.ListedColormap(color_tuples) + barplot = DataFrame([[1, 2, 3]]).plot(kind="bar", cmap=colormap) + assert color_tuples == [c.get_facecolor() for c in barplot.patches] + + def test_rcParams_bar_colors(self): + import matplotlib as mpl + + color_tuples = [(0.9, 0, 0, 1), (0, 0.9, 0, 1), (0, 0, 0.9, 1)] + with mpl.rc_context(rc={"axes.prop_cycle": mpl.cycler("color", color_tuples)}): + barplot = DataFrame([[1, 2, 3]]).plot(kind="bar") + assert color_tuples == [c.get_facecolor() for c in barplot.patches] + + def test_colors_of_columns_with_same_name(self): + # ISSUE 11136 -> https://github.com/pandas-dev/pandas/issues/11136 + # Creating a DataFrame with duplicate column labels and testing colors of them. + df = DataFrame({"b": [0, 1, 0], "a": [1, 2, 3]}) + df1 = DataFrame({"a": [2, 4, 6]}) + df_concat = pd.concat([df, df1], axis=1) + result = df_concat.plot() + for legend, line in zip(result.get_legend().legendHandles, result.lines): + assert legend.get_color() == line.get_color() + + def test_invalid_colormap(self): + df = DataFrame(np.random.randn(3, 2), columns=["A", "B"]) + + with pytest.raises(ValueError): + df.plot(colormap="invalid_colormap") diff --git a/pandas/tests/plotting/frame/test_frame_groupby.py b/pandas/tests/plotting/frame/test_frame_groupby.py new file mode 100644 index 0000000000000..9c1676d6d97fb --- /dev/null +++ b/pandas/tests/plotting/frame/test_frame_groupby.py @@ -0,0 +1,90 @@ +""" Test cases for DataFrame.plot """ + +import numpy as np +import pytest + +import pandas.util._test_decorators as td + +from pandas import DataFrame +import pandas._testing as tm +from pandas.tests.plotting.common import TestPlotBase + + +@td.skip_if_no_mpl +class TestDataFramePlotsGroupby(TestPlotBase): + def setup_method(self, method): + TestPlotBase.setup_method(self, method) + import matplotlib as mpl + + mpl.rcdefaults() + + self.tdf = tm.makeTimeDataFrame() + self.hexbin_df = DataFrame( + { + "A": np.random.uniform(size=20), + "B": np.random.uniform(size=20), + "C": np.arange(20) + np.random.uniform(size=20), + } + ) + + def _assert_ytickslabels_visibility(self, axes, expected): + for ax, exp in zip(axes, expected): + self._check_visible(ax.get_yticklabels(), visible=exp) + + def _assert_xtickslabels_visibility(self, axes, expected): + for ax, exp in zip(axes, expected): + self._check_visible(ax.get_xticklabels(), visible=exp) + + @pytest.mark.parametrize( + "kwargs, expected", + [ + # behavior without keyword + ({}, [True, False, True, False]), + # set sharey=True should be identical + ({"sharey": True}, [True, False, True, False]), + # sharey=False, all yticklabels should be visible + ({"sharey": False}, [True, True, True, True]), + ], + ) + def test_groupby_boxplot_sharey(self, kwargs, expected): + # https://github.com/pandas-dev/pandas/issues/20968 + # sharey can now be switched check whether the right + # pair of axes is turned on or off + df = DataFrame( + { + "a": [-1.43, -0.15, -3.70, -1.43, -0.14], + "b": [0.56, 0.84, 0.29, 0.56, 0.85], + "c": [0, 1, 2, 3, 1], + }, + index=[0, 1, 2, 3, 4], + ) + axes = df.groupby("c").boxplot(**kwargs) + self._assert_ytickslabels_visibility(axes, expected) + + @pytest.mark.parametrize( + "kwargs, expected", + [ + # behavior without keyword + ({}, [True, True, True, True]), + # set sharex=False should be identical + ({"sharex": False}, [True, True, True, True]), + # sharex=True, xticklabels should be visible + # only for bottom plots + ({"sharex": True}, [False, False, True, True]), + ], + ) + def test_groupby_boxplot_sharex(self, kwargs, expected): + # https://github.com/pandas-dev/pandas/issues/20968 + # sharex can now be switched check whether the right + # pair of axes is turned on or off + + df = DataFrame( + { + "a": [-1.43, -0.15, -3.70, -1.43, -0.14], + "b": [0.56, 0.84, 0.29, 0.56, 0.85], + "c": [0, 1, 2, 3, 1], + }, + index=[0, 1, 2, 3, 4], + ) + axes = df.groupby("c").boxplot(**kwargs) + self._assert_xtickslabels_visibility(axes, expected) diff --git a/pandas/tests/plotting/frame/test_frame_subplots.py b/pandas/tests/plotting/frame/test_frame_subplots.py new file mode 100644 index 0000000000000..413c5b8a87dc7 --- /dev/null +++ b/pandas/tests/plotting/frame/test_frame_subplots.py @@ -0,0 +1,677 @@ +""" Test cases for DataFrame.plot """ + +import string +import warnings + +import numpy as np +import pytest + +import pandas.util._test_decorators as td + +import pandas as pd +from pandas import DataFrame, Series, date_range +import pandas._testing as tm +from pandas.tests.plotting.common import TestPlotBase + +from pandas.io.formats.printing import pprint_thing + + +@td.skip_if_no_mpl +class TestDataFramePlotsSubplots(TestPlotBase): + def setup_method(self, method): + TestPlotBase.setup_method(self, method) + import matplotlib as mpl + + mpl.rcdefaults() + + self.tdf = tm.makeTimeDataFrame() + self.hexbin_df = DataFrame( + { + "A": np.random.uniform(size=20), + "B": np.random.uniform(size=20), + "C": np.arange(20) + np.random.uniform(size=20), + } + ) + + @pytest.mark.slow + def test_subplots(self): + df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) + + for kind in ["bar", "barh", "line", "area"]: + axes = df.plot(kind=kind, subplots=True, sharex=True, legend=True) + self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) + assert axes.shape == (3,) + + for ax, column in zip(axes, df.columns): + self._check_legend_labels(ax, labels=[pprint_thing(column)]) + + for ax in axes[:-2]: + self._check_visible(ax.xaxis) # xaxis must be visible for grid + self._check_visible(ax.get_xticklabels(), visible=False) + if not (kind == "bar" and self.mpl_ge_3_1_0): + # change https://github.com/pandas-dev/pandas/issues/26714 + self._check_visible(ax.get_xticklabels(minor=True), visible=False) + self._check_visible(ax.xaxis.get_label(), visible=False) + self._check_visible(ax.get_yticklabels()) + + self._check_visible(axes[-1].xaxis) + self._check_visible(axes[-1].get_xticklabels()) + self._check_visible(axes[-1].get_xticklabels(minor=True)) + self._check_visible(axes[-1].xaxis.get_label()) + self._check_visible(axes[-1].get_yticklabels()) + + axes = df.plot(kind=kind, subplots=True, sharex=False) + for ax in axes: + self._check_visible(ax.xaxis) + self._check_visible(ax.get_xticklabels()) + self._check_visible(ax.get_xticklabels(minor=True)) + self._check_visible(ax.xaxis.get_label()) + self._check_visible(ax.get_yticklabels()) + + axes = df.plot(kind=kind, subplots=True, legend=False) + for ax in axes: + assert ax.get_legend() is None + + @pytest.mark.slow + def test_subplots_timeseries(self): + idx = date_range(start="2014-07-01", freq="M", periods=10) + df = DataFrame(np.random.rand(10, 3), index=idx) + + for kind in ["line", "area"]: + axes = df.plot(kind=kind, subplots=True, sharex=True) + self._check_axes_shape(axes, axes_num=3, layout=(3, 1)) + + for ax in axes[:-2]: + # GH 7801 + self._check_visible(ax.xaxis) # xaxis must be visible for grid + self._check_visible(ax.get_xticklabels(), visible=False) + self._check_visible(ax.get_xticklabels(minor=True), visible=False) + self._check_visible(ax.xaxis.get_label(), visible=False) + self._check_visible(ax.get_yticklabels()) + + self._check_visible(axes[-1].xaxis) + self._check_visible(axes[-1].get_xticklabels()) + self._check_visible(axes[-1].get_xticklabels(minor=True)) + self._check_visible(axes[-1].xaxis.get_label()) + self._check_visible(axes[-1].get_yticklabels()) + self._check_ticks_props(axes, xrot=0) + + axes = df.plot(kind=kind, subplots=True, sharex=False, rot=45, fontsize=7) + for ax in axes: + self._check_visible(ax.xaxis) + self._check_visible(ax.get_xticklabels()) + self._check_visible(ax.get_xticklabels(minor=True)) + self._check_visible(ax.xaxis.get_label()) + self._check_visible(ax.get_yticklabels()) + self._check_ticks_props(ax, xlabelsize=7, xrot=45, ylabelsize=7) + + def test_subplots_timeseries_y_axis(self): + # GH16953 + data = { + "numeric": np.array([1, 2, 5]), + "timedelta": [ + pd.Timedelta(-10, unit="s"), + pd.Timedelta(10, unit="m"), + pd.Timedelta(10, unit="h"), + ], + "datetime_no_tz": [ + pd.to_datetime("2017-08-01 00:00:00"), + pd.to_datetime("2017-08-01 02:00:00"), + pd.to_datetime("2017-08-02 00:00:00"), + ], + "datetime_all_tz": [ + pd.to_datetime("2017-08-01 00:00:00", utc=True), + pd.to_datetime("2017-08-01 02:00:00", utc=True), + pd.to_datetime("2017-08-02 00:00:00", utc=True), + ], + "text": ["This", "should", "fail"], + } + testdata = DataFrame(data) + + y_cols = ["numeric", "timedelta", "datetime_no_tz", "datetime_all_tz"] + for col in y_cols: + ax = testdata.plot(y=col) + result = ax.get_lines()[0].get_data()[1] + expected = testdata[col].values + assert (result == expected).all() + + msg = "no numeric data to plot" + with pytest.raises(TypeError, match=msg): + testdata.plot(y="text") + + @pytest.mark.xfail(reason="not support for period, categorical, datetime_mixed_tz") + def test_subplots_timeseries_y_axis_not_supported(self): + """ + This test will fail for: + period: + since period isn't yet implemented in ``select_dtypes`` + and because it will need a custom value converter + + tick formatter (as was done for x-axis plots) + + categorical: + because it will need a custom value converter + + tick formatter (also doesn't work for x-axis, as of now) + + datetime_mixed_tz: + because of the way how pandas handles ``Series`` of + ``datetime`` objects with different timezone, + generally converting ``datetime`` objects in a tz-aware + form could help with this problem + """ + data = { + "numeric": np.array([1, 2, 5]), + "period": [ + pd.Period("2017-08-01 00:00:00", freq="H"), + pd.Period("2017-08-01 02:00", freq="H"), + pd.Period("2017-08-02 00:00:00", freq="H"), + ], + "categorical": pd.Categorical( + ["c", "b", "a"], categories=["a", "b", "c"], ordered=False + ), + "datetime_mixed_tz": [ + pd.to_datetime("2017-08-01 00:00:00", utc=True), + pd.to_datetime("2017-08-01 02:00:00"), + pd.to_datetime("2017-08-02 00:00:00"), + ], + } + testdata = DataFrame(data) + ax_period = testdata.plot(x="numeric", y="period") + assert ( + ax_period.get_lines()[0].get_data()[1] == testdata["period"].values + ).all() + ax_categorical = testdata.plot(x="numeric", y="categorical") + assert ( + ax_categorical.get_lines()[0].get_data()[1] + == testdata["categorical"].values + ).all() + ax_datetime_mixed_tz = testdata.plot(x="numeric", y="datetime_mixed_tz") + assert ( + ax_datetime_mixed_tz.get_lines()[0].get_data()[1] + == testdata["datetime_mixed_tz"].values + ).all() + + @pytest.mark.slow + def test_subplots_layout_multi_column(self): + # GH 6667 + df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) + + axes = df.plot(subplots=True, layout=(2, 2)) + self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) + assert axes.shape == (2, 2) + + axes = df.plot(subplots=True, layout=(-1, 2)) + self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) + assert axes.shape == (2, 2) + + axes = df.plot(subplots=True, layout=(2, -1)) + self._check_axes_shape(axes, axes_num=3, layout=(2, 2)) + assert axes.shape == (2, 2) + + axes = df.plot(subplots=True, layout=(1, 4)) + self._check_axes_shape(axes, axes_num=3, layout=(1, 4)) + assert axes.shape == (1, 4) + + axes = df.plot(subplots=True, layout=(-1, 4)) + self._check_axes_shape(axes, axes_num=3, layout=(1, 4)) + assert axes.shape == (1, 4) + + axes = df.plot(subplots=True, layout=(4, -1)) + self._check_axes_shape(axes, axes_num=3, layout=(4, 1)) + assert axes.shape == (4, 1) + + with pytest.raises(ValueError): + df.plot(subplots=True, layout=(1, 1)) + with pytest.raises(ValueError): + df.plot(subplots=True, layout=(-1, -1)) + + @pytest.mark.slow + @pytest.mark.parametrize( + "kwargs, expected_axes_num, expected_layout, expected_shape", + [ + ({}, 1, (1, 1), (1,)), + ({"layout": (3, 3)}, 1, (3, 3), (3, 3)), + ], + ) + def test_subplots_layout_single_column( + self, kwargs, expected_axes_num, expected_layout, expected_shape + ): + + # GH 6667 + df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10])) + axes = df.plot(subplots=True, **kwargs) + self._check_axes_shape( + axes, + axes_num=expected_axes_num, + layout=expected_layout, + ) + assert axes.shape == expected_shape + + @pytest.mark.slow + def test_subplots_warnings(self): + # GH 9464 + with tm.assert_produces_warning(None): + df = DataFrame(np.random.randn(100, 4)) + df.plot(subplots=True, layout=(3, 2)) + + df = DataFrame( + np.random.randn(100, 4), index=date_range("1/1/2000", periods=100) + ) + df.plot(subplots=True, layout=(3, 2)) + + @pytest.mark.slow + def test_subplots_multiple_axes(self): + # GH 5353, 6970, GH 7069 + fig, axes = self.plt.subplots(2, 3) + df = DataFrame(np.random.rand(10, 3), index=list(string.ascii_letters[:10])) + + returned = df.plot(subplots=True, ax=axes[0], sharex=False, sharey=False) + self._check_axes_shape(returned, axes_num=3, layout=(1, 3)) + assert returned.shape == (3,) + assert returned[0].figure is fig + # draw on second row + returned = df.plot(subplots=True, ax=axes[1], sharex=False, sharey=False) + self._check_axes_shape(returned, axes_num=3, layout=(1, 3)) + assert returned.shape == (3,) + assert returned[0].figure is fig + self._check_axes_shape(axes, axes_num=6, layout=(2, 3)) + tm.close() + + with pytest.raises(ValueError): + fig, axes = self.plt.subplots(2, 3) + # pass different number of axes from required + df.plot(subplots=True, ax=axes) + + # pass 2-dim axes and invalid layout + # invalid lauout should not affect to input and return value + # (show warning is tested in + # TestDataFrameGroupByPlots.test_grouped_box_multiple_axes + fig, axes = self.plt.subplots(2, 2) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + df = DataFrame(np.random.rand(10, 4), index=list(string.ascii_letters[:10])) + + returned = df.plot( + subplots=True, ax=axes, layout=(2, 1), sharex=False, sharey=False + ) + self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) + assert returned.shape == (4,) + + returned = df.plot( + subplots=True, ax=axes, layout=(2, -1), sharex=False, sharey=False + ) + self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) + assert returned.shape == (4,) + + returned = df.plot( + subplots=True, ax=axes, layout=(-1, 2), sharex=False, sharey=False + ) + self._check_axes_shape(returned, axes_num=4, layout=(2, 2)) + assert returned.shape == (4,) + + # single column + fig, axes = self.plt.subplots(1, 1) + df = DataFrame(np.random.rand(10, 1), index=list(string.ascii_letters[:10])) + + axes = df.plot(subplots=True, ax=[axes], sharex=False, sharey=False) + self._check_axes_shape(axes, axes_num=1, layout=(1, 1)) + assert axes.shape == (1,) + + def test_subplots_ts_share_axes(self): + # GH 3964 + fig, axes = self.plt.subplots(3, 3, sharex=True, sharey=True) + self.plt.subplots_adjust(left=0.05, right=0.95, hspace=0.3, wspace=0.3) + df = DataFrame( + np.random.randn(10, 9), + index=date_range(start="2014-07-01", freq="M", periods=10), + ) + for i, ax in enumerate(axes.ravel()): + df[i].plot(ax=ax, fontsize=5) + + # Rows other than bottom should not be visible + for ax in axes[0:-1].ravel(): + self._check_visible(ax.get_xticklabels(), visible=False) + + # Bottom row should be visible + for ax in axes[-1].ravel(): + self._check_visible(ax.get_xticklabels(), visible=True) + + # First column should be visible + for ax in axes[[0, 1, 2], [0]].ravel(): + self._check_visible(ax.get_yticklabels(), visible=True) + + # Other columns should not be visible + for ax in axes[[0, 1, 2], [1]].ravel(): + self._check_visible(ax.get_yticklabels(), visible=False) + for ax in axes[[0, 1, 2], [2]].ravel(): + self._check_visible(ax.get_yticklabels(), visible=False) + + def test_subplots_sharex_axes_existing_axes(self): + # GH 9158 + d = {"A": [1.0, 2.0, 3.0, 4.0], "B": [4.0, 3.0, 2.0, 1.0], "C": [5, 1, 3, 4]} + df = DataFrame(d, index=date_range("2014 10 11", "2014 10 14")) + + axes = df[["A", "B"]].plot(subplots=True) + df["C"].plot(ax=axes[0], secondary_y=True) + + self._check_visible(axes[0].get_xticklabels(), visible=False) + self._check_visible(axes[1].get_xticklabels(), visible=True) + for ax in axes.ravel(): + self._check_visible(ax.get_yticklabels(), visible=True) + + @pytest.mark.slow + def test_subplots_dup_columns(self): + # GH 10962 + df = DataFrame(np.random.rand(5, 5), columns=list("aaaaa")) + axes = df.plot(subplots=True) + for ax in axes: + self._check_legend_labels(ax, labels=["a"]) + assert len(ax.lines) == 1 + tm.close() + + axes = df.plot(subplots=True, secondary_y="a") + for ax in axes: + # (right) is only attached when subplots=False + self._check_legend_labels(ax, labels=["a"]) + assert len(ax.lines) == 1 + tm.close() + + ax = df.plot(secondary_y="a") + self._check_legend_labels(ax, labels=["a (right)"] * 5) + assert len(ax.lines) == 0 + assert len(ax.right_ax.lines) == 5 + + @pytest.mark.slow + def test_bar_log_no_subplots(self): + # GH3254, GH3298 matplotlib/matplotlib#1882, #1892 + # regressions in 1.2.1 + expected = np.array([0.1, 1.0, 10.0, 100]) + + # no subplots + df = DataFrame({"A": [3] * 5, "B": list(range(1, 6))}, index=range(5)) + ax = df.plot.bar(grid=True, log=True) + tm.assert_numpy_array_equal(ax.yaxis.get_ticklocs(), expected) + + @pytest.mark.slow + def test_bar_log_subplots(self): + expected = np.array([0.1, 1.0, 10.0, 100.0, 1000.0, 1e4]) + + ax = DataFrame([Series([200, 300]), Series([300, 500])]).plot.bar( + log=True, subplots=True + ) + + tm.assert_numpy_array_equal(ax[0].yaxis.get_ticklocs(), expected) + tm.assert_numpy_array_equal(ax[1].yaxis.get_ticklocs(), expected) + + @pytest.mark.slow + def test_boxplot_subplots_return_type(self): + df = self.hist_df + + # normal style: return_type=None + result = df.plot.box(subplots=True) + assert isinstance(result, Series) + self._check_box_return_type( + result, None, expected_keys=["height", "weight", "category"] + ) + + for t in ["dict", "axes", "both"]: + returned = df.plot.box(return_type=t, subplots=True) + self._check_box_return_type( + returned, + t, + expected_keys=["height", "weight", "category"], + check_ax_title=False, + ) + + @pytest.mark.slow + def test_df_subplots_patterns_minorticks(self): + # GH 10657 + import matplotlib.pyplot as plt + + df = DataFrame( + np.random.randn(10, 2), + index=date_range("1/1/2000", periods=10), + columns=list("AB"), + ) + + # shared subplots + fig, axes = plt.subplots(2, 1, sharex=True) + axes = df.plot(subplots=True, ax=axes) + for ax in axes: + assert len(ax.lines) == 1 + self._check_visible(ax.get_yticklabels(), visible=True) + # xaxis of 1st ax must be hidden + self._check_visible(axes[0].get_xticklabels(), visible=False) + self._check_visible(axes[0].get_xticklabels(minor=True), visible=False) + self._check_visible(axes[1].get_xticklabels(), visible=True) + self._check_visible(axes[1].get_xticklabels(minor=True), visible=True) + tm.close() + + fig, axes = plt.subplots(2, 1) + with tm.assert_produces_warning(UserWarning): + axes = df.plot(subplots=True, ax=axes, sharex=True) + for ax in axes: + assert len(ax.lines) == 1 + self._check_visible(ax.get_yticklabels(), visible=True) + # xaxis of 1st ax must be hidden + self._check_visible(axes[0].get_xticklabels(), visible=False) + self._check_visible(axes[0].get_xticklabels(minor=True), visible=False) + self._check_visible(axes[1].get_xticklabels(), visible=True) + self._check_visible(axes[1].get_xticklabels(minor=True), visible=True) + tm.close() + + # not shared + fig, axes = plt.subplots(2, 1) + axes = df.plot(subplots=True, ax=axes) + for ax in axes: + assert len(ax.lines) == 1 + self._check_visible(ax.get_yticklabels(), visible=True) + self._check_visible(ax.get_xticklabels(), visible=True) + self._check_visible(ax.get_xticklabels(minor=True), visible=True) + tm.close() + + def test_subplots_sharex_false(self): + # test when sharex is set to False, two plots should have different + # labels, GH 25160 + df = DataFrame(np.random.rand(10, 2)) + df.iloc[5:, 1] = np.nan + df.iloc[:5, 0] = np.nan + + figs, axs = self.plt.subplots(2, 1) + df.plot.line(ax=axs, subplots=True, sharex=False) + + expected_ax1 = np.arange(4.5, 10, 0.5) + expected_ax2 = np.arange(-0.5, 5, 0.5) + + tm.assert_numpy_array_equal(axs[0].get_xticks(), expected_ax1) + tm.assert_numpy_array_equal(axs[1].get_xticks(), expected_ax2) + + @pytest.mark.parametrize( + "index_name, old_label, new_label", + [ + (None, "", "new"), + ("old", "old", "new"), + (None, "", ""), + (None, "", 1), + (None, "", [1, 2]), + ], + ) + @pytest.mark.parametrize("kind", ["line", "area", "bar"]) + def test_xlabel_ylabel_dataframe_subplots( + self, kind, index_name, old_label, new_label + ): + # GH 9093 + df = DataFrame([[1, 2], [2, 5]], columns=["Type A", "Type B"]) + df.index.name = index_name + + # default is the ylabel is not shown and xlabel is index name + axes = df.plot(kind=kind, subplots=True) + assert all(ax.get_ylabel() == "" for ax in axes) + assert all(ax.get_xlabel() == old_label for ax in axes) + + # old xlabel will be overriden and assigned ylabel will be used as ylabel + axes = df.plot(kind=kind, ylabel=new_label, xlabel=new_label, subplots=True) + assert all(ax.get_ylabel() == str(new_label) for ax in axes) + assert all(ax.get_xlabel() == str(new_label) for ax in axes) + + @pytest.mark.slow + @pytest.mark.parametrize( + "kwargs", + [ + # stacked center + dict(kind="bar", stacked=True), + dict(kind="bar", stacked=True, width=0.9), + dict(kind="barh", stacked=True), + dict(kind="barh", stacked=True, width=0.9), + # center + dict(kind="bar", stacked=False), + dict(kind="bar", stacked=False, width=0.9), + dict(kind="barh", stacked=False), + dict(kind="barh", stacked=False, width=0.9), + # subplots center + dict(kind="bar", subplots=True), + dict(kind="bar", subplots=True, width=0.9), + dict(kind="barh", subplots=True), + dict(kind="barh", subplots=True, width=0.9), + # align edge + dict(kind="bar", stacked=True, align="edge"), + dict(kind="bar", stacked=True, width=0.9, align="edge"), + dict(kind="barh", stacked=True, align="edge"), + dict(kind="barh", stacked=True, width=0.9, align="edge"), + dict(kind="bar", stacked=False, align="edge"), + dict(kind="bar", stacked=False, width=0.9, align="edge"), + dict(kind="barh", stacked=False, align="edge"), + dict(kind="barh", stacked=False, width=0.9, align="edge"), + dict(kind="bar", subplots=True, align="edge"), + dict(kind="bar", subplots=True, width=0.9, align="edge"), + dict(kind="barh", subplots=True, align="edge"), + dict(kind="barh", subplots=True, width=0.9, align="edge"), + ], + ) + def test_bar_align_multiple_columns(self, kwargs): + # GH2157 + df = DataFrame({"A": [3] * 5, "B": list(range(5))}, index=range(5)) + self._check_bar_alignment(df, **kwargs) + + @pytest.mark.slow + @pytest.mark.parametrize( + "kwargs", + [ + dict(kind="bar", stacked=False), + dict(kind="bar", stacked=True), + dict(kind="barh", stacked=False), + dict(kind="barh", stacked=True), + dict(kind="bar", subplots=True), + dict(kind="barh", subplots=True), + ], + ) + def test_bar_align_single_column(self, kwargs): + df = DataFrame(np.random.randn(5)) + self._check_bar_alignment(df, **kwargs) + + @pytest.mark.slow + @pytest.mark.parametrize( + "kwargs", + [ + {"kind": "bar", "stacked": False}, + {"kind": "bar", "stacked": True}, + {"kind": "barh", "stacked": False}, + {"kind": "barh", "stacked": True}, + {"kind": "bar", "subplots": True}, + {"kind": "barh", "subplots": True}, + ], + ) + def test_bar_barwidth_position(self, kwargs): + df = DataFrame(np.random.randn(5, 5)) + self._check_bar_alignment(df, width=0.9, position=0.2, **kwargs) + + @pytest.mark.slow + def test_bar_barwidth_position_int(self): + # GH 12979 + df = DataFrame(np.random.randn(5, 5)) + + for w in [1, 1.0]: + ax = df.plot.bar(stacked=True, width=w) + ticks = ax.xaxis.get_ticklocs() + tm.assert_numpy_array_equal(ticks, np.array([0, 1, 2, 3, 4])) + assert ax.get_xlim() == (-0.75, 4.75) + # check left-edge of bars + assert ax.patches[0].get_x() == -0.5 + assert ax.patches[-1].get_x() == 3.5 + + self._check_bar_alignment(df, kind="bar", stacked=True, width=1) + self._check_bar_alignment(df, kind="barh", stacked=False, width=1) + self._check_bar_alignment(df, kind="barh", stacked=True, width=1) + self._check_bar_alignment(df, kind="bar", subplots=True, width=1) + self._check_bar_alignment(df, kind="barh", subplots=True, width=1) + + def _check_bar_alignment( + self, + df, + kind="bar", + stacked=False, + subplots=False, + align="center", + width=0.5, + position=0.5, + ): + + axes = df.plot( + kind=kind, + stacked=stacked, + subplots=subplots, + align=align, + width=width, + position=position, + grid=True, + ) + + axes = self._flatten_visible(axes) + + for ax in axes: + if kind == "bar": + axis = ax.xaxis + ax_min, ax_max = ax.get_xlim() + min_edge = min(p.get_x() for p in ax.patches) + max_edge = max(p.get_x() + p.get_width() for p in ax.patches) + elif kind == "barh": + axis = ax.yaxis + ax_min, ax_max = ax.get_ylim() + min_edge = min(p.get_y() for p in ax.patches) + max_edge = max(p.get_y() + p.get_height() for p in ax.patches) + else: + raise ValueError + + # GH 7498 + # compare margins between lim and bar edges + tm.assert_almost_equal(ax_min, min_edge - 0.25) + tm.assert_almost_equal(ax_max, max_edge + 0.25) + + p = ax.patches[0] + if kind == "bar" and (stacked is True or subplots is True): + edge = p.get_x() + center = edge + p.get_width() * position + elif kind == "bar" and stacked is False: + center = p.get_x() + p.get_width() * len(df.columns) * position + edge = p.get_x() + elif kind == "barh" and (stacked is True or subplots is True): + center = p.get_y() + p.get_height() * position + edge = p.get_y() + elif kind == "barh" and stacked is False: + center = p.get_y() + p.get_height() * len(df.columns) * position + edge = p.get_y() + else: + raise ValueError + + # Check the ticks locates on integer + assert (axis.get_ticklocs() == np.arange(len(df))).all() + + if align == "center": + # Check whether the bar locates on center + tm.assert_almost_equal(axis.get_ticklocs()[0], center) + elif align == "edge": + # Check whether the bar's edge starts from the tick + tm.assert_almost_equal(axis.get_ticklocs()[0], edge) + else: + raise ValueError + + return axes