From 3f0db16f94c792dc4e0b4638241ae17e8c56e9e2 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sat, 30 Sep 2017 16:33:02 -0400 Subject: [PATCH 01/14] BUG: GH17525 Removed the random seed reset in _style.py --- pandas/plotting/_style.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index 8cb4e30e0d91c..c8472a6fdb364 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -114,7 +114,6 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', import random def random_color(column): - random.seed(column) return [random.random() for _ in range(3)] colors = lmap(random_color, lrange(num_colors)) From 6ec894b2005101d1e46e975086c09c5302d1bb73 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sat, 30 Sep 2017 16:42:02 -0400 Subject: [PATCH 02/14] Added bug documentation to doc/source/whatsnew/v0.21.0.txt --- doc/source/whatsnew/v0.21.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index e0e0c18052550..d5f8c3027d5af 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -614,6 +614,7 @@ Plotting - Line plots no longer assume monotonic x data when calculating xlims, they show the entire lines now even for unsorted x data. (:issue:`11310`, :issue:`11471`) - With matplotlib 2.0.0 and above, calculation of x limits for line plots is left to matplotlib, so that its new default settings are applied. (:issue:`15495`) - Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`) +- Bug in ``plotting._style._get_standard_colors`` resetting the random seed when generating random colors (:issue:`17525`) Groupby/Resample/Rolling From f38bf559091240a28e4adeae40f4157279b16f38 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sat, 30 Sep 2017 17:25:59 -0400 Subject: [PATCH 03/14] BUG: GH17525 Change function _get_standard_colors to avoid resetting the random seed globally --- pandas/plotting/_style.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index c8472a6fdb364..e4bc8fbb82a4b 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -114,7 +114,11 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', import random def random_color(column): - return [random.random() for _ in range(3)] + rstate = random.getstate() # this is to avoid resetting the seed globally + random.seed(column) + color = [random.random() for _ in range(3)] + random.setstate(rstate) + return color colors = lmap(random_color, lrange(num_colors)) else: From 831f70fdd38127d9c8620635c8f49f5b6029f049 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sat, 30 Sep 2017 17:29:35 -0400 Subject: [PATCH 04/14] Flake8 formatting compliance --- pandas/plotting/_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index e4bc8fbb82a4b..7d6eeaf99ee01 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -114,7 +114,7 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', import random def random_color(column): - rstate = random.getstate() # this is to avoid resetting the seed globally + rstate = random.getstate() # to avoid resetting the seed random.seed(column) color = [random.random() for _ in range(3)] random.setstate(rstate) From 3bf3c0e00a084c67a8de1571c575d8495d89a94e Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sun, 1 Oct 2017 10:56:36 -0400 Subject: [PATCH 05/14] Added docstring to internal `random_color` function --- pandas/plotting/_style.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index 7d6eeaf99ee01..a2daefa074808 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -114,7 +114,9 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', import random def random_color(column): - rstate = random.getstate() # to avoid resetting the seed + """ Returns a random color represented as a list of length 3""" + # GH17525 use setstate/getstate to avoid resetting the seed + rstate = random.getstate() random.seed(column) color = [random.random() for _ in range(3)] random.setstate(rstate) From 2f3da72c2706364afd483c2cb6dfa8d4fc44813d Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sun, 1 Oct 2017 11:24:22 -0400 Subject: [PATCH 06/14] BUG: GH17525 Added test to check for random seed reset --- pandas/tests/plotting/test_misc.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pandas/tests/plotting/test_misc.py b/pandas/tests/plotting/test_misc.py index c4795ea1e1eca..f2259eaccee3e 100644 --- a/pandas/tests/plotting/test_misc.py +++ b/pandas/tests/plotting/test_misc.py @@ -284,3 +284,20 @@ def test_subplot_titles(self): title=title[:-1]) title_list = [ax.get_title() for sublist in plot for ax in sublist] assert title_list == title[:3] + [''] + + def test_get_standard_colors_random_seed(self): + """ For #17525 """ + df = DataFrame(np.zeros((10,10))) + + # Make sure that the random seed isn't reset by _get_standard_colors + plotting.parallel_coordinates(df,0) + rand1 = random.random() + plotting.parallel_coordinates(df,0) + rand2 = random.random() + assert rand1 != rand2 + + # Make sure it produces the same colors every time it's called + from pandas.plotting._style import _get_standard_colors + color1 = _get_standard_colors(1, color_type='random') + color2 = _get_standard_colors(1, color_type='random') + assert color1 == color2 From bf9678b4c30c2ae4a856fc13db93ce6c007caa0d Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sun, 1 Oct 2017 11:29:17 -0400 Subject: [PATCH 07/14] Fixed whitespace for PEP8 --- pandas/tests/plotting/test_misc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/plotting/test_misc.py b/pandas/tests/plotting/test_misc.py index f2259eaccee3e..d6f00ba943822 100644 --- a/pandas/tests/plotting/test_misc.py +++ b/pandas/tests/plotting/test_misc.py @@ -287,12 +287,12 @@ def test_subplot_titles(self): def test_get_standard_colors_random_seed(self): """ For #17525 """ - df = DataFrame(np.zeros((10,10))) + df = DataFrame(np.zeros((10, 10))) # Make sure that the random seed isn't reset by _get_standard_colors - plotting.parallel_coordinates(df,0) + plotting.parallel_coordinates(df, 0) rand1 = random.random() - plotting.parallel_coordinates(df,0) + plotting.parallel_coordinates(df, 0) rand2 = random.random() assert rand1 != rand2 From f711dd1e5a80c3a48a8d802ad4d97b7f235c10fd Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sun, 1 Oct 2017 15:29:55 -0400 Subject: [PATCH 08/14] Used pandas.core.common._random_state to avoid resetting the seed --- pandas/plotting/_style.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index a2daefa074808..788c72164ced1 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -111,16 +111,13 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', if isinstance(colors, compat.string_types): colors = list(colors) elif color_type == 'random': - import random + from pandas.core.common import _random_state def random_color(column): """ Returns a random color represented as a list of length 3""" - # GH17525 use setstate/getstate to avoid resetting the seed - rstate = random.getstate() - random.seed(column) - color = [random.random() for _ in range(3)] - random.setstate(rstate) - return color + # GH17525 use common._random_state to avoid resetting the seed + rs = _random_state() + return rs.rand(3) colors = lmap(random_color, lrange(num_colors)) else: From 92dbac39ace578091d4e2c837913c601e2bd88d2 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Sun, 1 Oct 2017 15:32:15 -0400 Subject: [PATCH 09/14] Changed whatsnew to reference the user-visible issue --- doc/source/whatsnew/v0.21.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index d5f8c3027d5af..bc096b16ff3c5 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -614,7 +614,7 @@ Plotting - Line plots no longer assume monotonic x data when calculating xlims, they show the entire lines now even for unsorted x data. (:issue:`11310`, :issue:`11471`) - With matplotlib 2.0.0 and above, calculation of x limits for line plots is left to matplotlib, so that its new default settings are applied. (:issue:`15495`) - Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`) -- Bug in ``plotting._style._get_standard_colors`` resetting the random seed when generating random colors (:issue:`17525`) +- Bug in ``plotting._style._get_standard_colors`` causing ``plotting.parallel_coordinates`` to reset the random seed when using random colors (:issue:`17525`) Groupby/Resample/Rolling From 4041102a13b1b013845b55979d0395b54f1f3b36 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Mon, 2 Oct 2017 08:29:41 -0400 Subject: [PATCH 10/14] Add tolist() to _get_standard_colors to return the correct type --- pandas/plotting/_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index 788c72164ced1..0005eb03a4ba6 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -117,7 +117,7 @@ def random_color(column): """ Returns a random color represented as a list of length 3""" # GH17525 use common._random_state to avoid resetting the seed rs = _random_state() - return rs.rand(3) + return rs.rand(3).tolist() colors = lmap(random_color, lrange(num_colors)) else: From 6e4e3e57dbdff8d2b30962c53f66f2705174d17b Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Mon, 2 Oct 2017 08:30:40 -0400 Subject: [PATCH 11/14] Changed whatsnew to be clearer --- doc/source/whatsnew/v0.21.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index bc096b16ff3c5..da3cf965cb81a 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -614,7 +614,7 @@ Plotting - Line plots no longer assume monotonic x data when calculating xlims, they show the entire lines now even for unsorted x data. (:issue:`11310`, :issue:`11471`) - With matplotlib 2.0.0 and above, calculation of x limits for line plots is left to matplotlib, so that its new default settings are applied. (:issue:`15495`) - Bug in ``Series.plot.bar`` or ``DataFramee.plot.bar`` with ``y`` not respecting user-passed ``color`` (:issue:`16822`) -- Bug in ``plotting._style._get_standard_colors`` causing ``plotting.parallel_coordinates`` to reset the random seed when using random colors (:issue:`17525`) +- Bug causing ``plotting.parallel_coordinates`` to reset the random seed when using random colors (:issue:`17525`) Groupby/Resample/Rolling From e4f1b0eee588775e47ccbc5c81bf7e3678db4dd4 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Mon, 2 Oct 2017 08:35:15 -0400 Subject: [PATCH 12/14] Set the random seed in `random_color` to ensure consistent colors are returned --- pandas/plotting/_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index 0005eb03a4ba6..e8c4d17af4b0e 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -116,7 +116,7 @@ def _get_standard_colors(num_colors=None, colormap=None, color_type='default', def random_color(column): """ Returns a random color represented as a list of length 3""" # GH17525 use common._random_state to avoid resetting the seed - rs = _random_state() + rs = _random_state(column) return rs.rand(3).tolist() colors = lmap(random_color, lrange(num_colors)) From 54b21381284512c6756bc21adc5306b5d57045d5 Mon Sep 17 00:00:00 2001 From: Chris Mazzullo Date: Mon, 2 Oct 2017 18:10:45 -0400 Subject: [PATCH 13/14] Removed `range` import --- pandas/plotting/_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/plotting/_style.py b/pandas/plotting/_style.py index e8c4d17af4b0e..bd581c93f1011 100644 --- a/pandas/plotting/_style.py +++ b/pandas/plotting/_style.py @@ -9,7 +9,7 @@ import numpy as np from pandas.core.dtypes.common import is_list_like -from pandas.compat import range, lrange, lmap +from pandas.compat import lrange, lmap import pandas.compat as compat from pandas.plotting._compat import _mpl_ge_2_0_0 From 092c2d52cc61d7673e4e07d865905cf2b10c56a2 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Tue, 3 Oct 2017 10:06:40 +0200 Subject: [PATCH 14/14] change test comment --- pandas/tests/plotting/test_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/plotting/test_misc.py b/pandas/tests/plotting/test_misc.py index d6f00ba943822..957369a20f16e 100644 --- a/pandas/tests/plotting/test_misc.py +++ b/pandas/tests/plotting/test_misc.py @@ -286,7 +286,7 @@ def test_subplot_titles(self): assert title_list == title[:3] + [''] def test_get_standard_colors_random_seed(self): - """ For #17525 """ + # GH17525 df = DataFrame(np.zeros((10, 10))) # Make sure that the random seed isn't reset by _get_standard_colors