From cc56b528d9dc2dc0645c537bf5e48dd031fef21e Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Wed, 22 Jan 2020 14:37:41 +0000 Subject: [PATCH 1/9] :bug: no longer raise user warning when plotting tz aware time series --- doc/source/whatsnew/v1.0.1.rst | 2 +- pandas/plotting/_matplotlib/timeseries.py | 5 ++++- pandas/tests/plotting/test_datetimelike.py | 11 +++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/doc/source/whatsnew/v1.0.1.rst b/doc/source/whatsnew/v1.0.1.rst index 16d9d341f785d..6e053208f7692 100644 --- a/doc/source/whatsnew/v1.0.1.rst +++ b/doc/source/whatsnew/v1.0.1.rst @@ -97,7 +97,7 @@ I/O Plotting ^^^^^^^^ -- +- Plotting tz-aware timeseries no longer gives UserWarning (:issue:`31205`) - Groupby/resample/rolling diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index dd048114142f3..a6b0b91f99fa8 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -1,6 +1,7 @@ # TODO: Use the fact that axis can have units to simplify the process import functools +import warnings import numpy as np @@ -251,7 +252,9 @@ def _maybe_convert_index(ax, data): freq = frequencies.get_period_alias(freq) if isinstance(data.index, ABCDatetimeIndex): - data = data.to_period(freq=freq) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=UserWarning) + data = data.to_period(freq=freq) elif isinstance(data.index, ABCPeriodIndex): data.index = data.index.asfreq(freq=freq) return data diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index 84d298cd7c6fe..500fb69b028c4 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -43,19 +43,14 @@ def setup_method(self, method): def teardown_method(self, method): tm.close() - # Ignore warning - # ``` - # Converting to PeriodArray/Index representation will drop timezone information. - # ``` - # which occurs for UTC-like timezones. @pytest.mark.slow - @pytest.mark.filterwarnings("ignore:msg:UserWarning") - def test_ts_plot_with_tz(self, tz_aware_fixture): - # GH2877, GH17173 + def test_ts_plot_with_tz(self, tz_aware_fixture, recwarn): + # GH2877, GH17173, GH31205 tz = tz_aware_fixture index = date_range("1/1/2011", periods=2, freq="H", tz=tz) ts = Series([188.5, 328.25], index=index) _check_plot_works(ts.plot) + assert not any(isinstance(i.message, UserWarning) for i in recwarn) def test_fontsize_set_correctly(self): # For issue #8765 From 55f7aacb41aa2080737c5731058b707106b0e0f9 Mon Sep 17 00:00:00 2001 From: Marco Gorelli Date: Fri, 24 Jan 2020 10:02:01 +0000 Subject: [PATCH 2/9] :ok_hand: use pandas testing module to check for no warnings, dont ignore warnings, remove whatsnewentry --- pandas/plotting/_matplotlib/timeseries.py | 5 +---- pandas/tests/plotting/test_datetimelike.py | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index a6b0b91f99fa8..3abce690cbe6b 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -1,7 +1,6 @@ # TODO: Use the fact that axis can have units to simplify the process import functools -import warnings import numpy as np @@ -252,9 +251,7 @@ def _maybe_convert_index(ax, data): freq = frequencies.get_period_alias(freq) if isinstance(data.index, ABCDatetimeIndex): - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=UserWarning) - data = data.to_period(freq=freq) + data = data.tz_localize(None).to_period(freq=freq) elif isinstance(data.index, ABCPeriodIndex): data.index = data.index.asfreq(freq=freq) return data diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index 500fb69b028c4..dbe728f5238c7 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -44,13 +44,13 @@ def teardown_method(self, method): tm.close() @pytest.mark.slow - def test_ts_plot_with_tz(self, tz_aware_fixture, recwarn): + def test_ts_plot_with_tz(self, tz_aware_fixture): # GH2877, GH17173, GH31205 tz = tz_aware_fixture index = date_range("1/1/2011", periods=2, freq="H", tz=tz) ts = Series([188.5, 328.25], index=index) - _check_plot_works(ts.plot) - assert not any(isinstance(i.message, UserWarning) for i in recwarn) + with tm.assert_produces_warning(None): + _check_plot_works(ts.plot) def test_fontsize_set_correctly(self): # For issue #8765 From ecbed59f23c75cc40491bf5b03ec806db42cbb7f Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sat, 1 Feb 2020 18:48:09 +0000 Subject: [PATCH 3/9] check first point is in correct timezone --- pandas/tests/mytest.py | 10 ++++++++++ pandas/tests/plotting/test_datetimelike.py | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 pandas/tests/mytest.py diff --git a/pandas/tests/mytest.py b/pandas/tests/mytest.py new file mode 100644 index 0000000000000..78ffe5555ea07 --- /dev/null +++ b/pandas/tests/mytest.py @@ -0,0 +1,10 @@ +import pandas as pd +import numpy as np + +def test_me(): + df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'], + 'key2' : ['one', 'two', 'one', 'two', 'one'], + 'key3' : ['three', 'three', 'three', 'six', 'six'], + 'data1' : np.random.randn(5), + 'data2' : np.random.randn(5)}) + df.groupby('key1').min() diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index dbe728f5238c7..4aa6371c56d79 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -1,6 +1,7 @@ """ Test cases for time series specific (freq conversion, etc) """ from datetime import date, datetime, time, timedelta import pickle +import re import sys import numpy as np @@ -50,6 +51,14 @@ def test_ts_plot_with_tz(self, tz_aware_fixture): index = date_range("1/1/2011", periods=2, freq="H", tz=tz) ts = Series([188.5, 328.25], index=index) with tm.assert_produces_warning(None): + fig, ax = self.plt.subplots() + ts.plot(ax=ax) + fig.canvas.draw() + labels = [i.get_text() for i in ax.get_xticklabels()] + # Extract H:M component, check first point is in correct timezone. + # NOTE: this test could be updated once GH 31548 is fixed, + # so that the last point is checked as well. + assert re.findall(r"[^:]*(\d{2}:\d{2})", labels[0]) == ["00:00"] _check_plot_works(ts.plot) def test_fontsize_set_correctly(self): From dc3f95cfced82a82801a1568a3d3fbd39cab5e1b Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sat, 1 Feb 2020 19:13:46 +0000 Subject: [PATCH 4/9] remove accidentally committed file --- pandas/tests/mytest.py | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 pandas/tests/mytest.py diff --git a/pandas/tests/mytest.py b/pandas/tests/mytest.py deleted file mode 100644 index 78ffe5555ea07..0000000000000 --- a/pandas/tests/mytest.py +++ /dev/null @@ -1,10 +0,0 @@ -import pandas as pd -import numpy as np - -def test_me(): - df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'], - 'key2' : ['one', 'two', 'one', 'two', 'one'], - 'key3' : ['three', 'three', 'three', 'six', 'six'], - 'data1' : np.random.randn(5), - 'data2' : np.random.randn(5)}) - df.groupby('key1').min() From a94bf561b2b987ee67a5f6afa67fb2edc25bb125 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sat, 1 Feb 2020 19:17:32 +0000 Subject: [PATCH 5/9] simplify regex --- pandas/tests/plotting/test_datetimelike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index 4aa6371c56d79..98938b0a7f997 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -58,7 +58,7 @@ def test_ts_plot_with_tz(self, tz_aware_fixture): # Extract H:M component, check first point is in correct timezone. # NOTE: this test could be updated once GH 31548 is fixed, # so that the last point is checked as well. - assert re.findall(r"[^:]*(\d{2}:\d{2})", labels[0]) == ["00:00"] + assert re.findall(r"\d{2}:\d{2}", labels[0])[0] == "00:00" _check_plot_works(ts.plot) def test_fontsize_set_correctly(self): From 363b3285ea2247b4ed216ba3b026aee5edb4c277 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sat, 1 Feb 2020 20:20:10 +0000 Subject: [PATCH 6/9] try tz_convert --- pandas/plotting/_matplotlib/timeseries.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index 3abce690cbe6b..7ba840b49307c 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -251,7 +251,11 @@ def _maybe_convert_index(ax, data): freq = frequencies.get_period_alias(freq) if isinstance(data.index, ABCDatetimeIndex): - data = data.tz_localize(None).to_period(freq=freq) + if data.index.tz is not None: + data = data.tz_convert(None).to_period(freq=freq) + else: + # can't convert tz-naive + data = data.to_period(freq=freq) elif isinstance(data.index, ABCPeriodIndex): data.index = data.index.asfreq(freq=freq) return data From cceca718261f36112702181de5758ba00fcb32c2 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sun, 2 Feb 2020 11:42:31 +0000 Subject: [PATCH 7/9] debugging CI failure --- pandas/tests/plotting/test_datetimelike.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index 98938b0a7f997..69d76c974b9e6 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -58,7 +58,8 @@ def test_ts_plot_with_tz(self, tz_aware_fixture): # Extract H:M component, check first point is in correct timezone. # NOTE: this test could be updated once GH 31548 is fixed, # so that the last point is checked as well. - assert re.findall(r"\d{2}:\d{2}", labels[0])[0] == "00:00" + assert labels == [] + assert re.findall(r"[^:]?(\d{2}:\d{2})", labels[0])[0] == "00:00" _check_plot_works(ts.plot) def test_fontsize_set_correctly(self): From ecd4abbb1615b859e5dde15f38b3ea7cfee0ab7f Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sun, 2 Feb 2020 17:23:31 +0000 Subject: [PATCH 8/9] remove test checking labels --- pandas/tests/plotting/test_datetimelike.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pandas/tests/plotting/test_datetimelike.py b/pandas/tests/plotting/test_datetimelike.py index 69d76c974b9e6..dbe728f5238c7 100644 --- a/pandas/tests/plotting/test_datetimelike.py +++ b/pandas/tests/plotting/test_datetimelike.py @@ -1,7 +1,6 @@ """ Test cases for time series specific (freq conversion, etc) """ from datetime import date, datetime, time, timedelta import pickle -import re import sys import numpy as np @@ -51,15 +50,6 @@ def test_ts_plot_with_tz(self, tz_aware_fixture): index = date_range("1/1/2011", periods=2, freq="H", tz=tz) ts = Series([188.5, 328.25], index=index) with tm.assert_produces_warning(None): - fig, ax = self.plt.subplots() - ts.plot(ax=ax) - fig.canvas.draw() - labels = [i.get_text() for i in ax.get_xticklabels()] - # Extract H:M component, check first point is in correct timezone. - # NOTE: this test could be updated once GH 31548 is fixed, - # so that the last point is checked as well. - assert labels == [] - assert re.findall(r"[^:]?(\d{2}:\d{2})", labels[0])[0] == "00:00" _check_plot_works(ts.plot) def test_fontsize_set_correctly(self): From 6e2d3aeb6179d40abfb68fdcc5b064a1d6b0bc59 Mon Sep 17 00:00:00 2001 From: MarcoGorelli Date: Sun, 2 Feb 2020 17:27:24 +0000 Subject: [PATCH 9/9] revert to tz_localize, as tz_convert didn't help the failing CI test and tz_localize was previously approved --- pandas/plotting/_matplotlib/timeseries.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pandas/plotting/_matplotlib/timeseries.py b/pandas/plotting/_matplotlib/timeseries.py index 7ba840b49307c..3abce690cbe6b 100644 --- a/pandas/plotting/_matplotlib/timeseries.py +++ b/pandas/plotting/_matplotlib/timeseries.py @@ -251,11 +251,7 @@ def _maybe_convert_index(ax, data): freq = frequencies.get_period_alias(freq) if isinstance(data.index, ABCDatetimeIndex): - if data.index.tz is not None: - data = data.tz_convert(None).to_period(freq=freq) - else: - # can't convert tz-naive - data = data.to_period(freq=freq) + data = data.tz_localize(None).to_period(freq=freq) elif isinstance(data.index, ABCPeriodIndex): data.index = data.index.asfreq(freq=freq) return data