diff --git a/plotly/tests/test_optional/test_figure_factory.py b/plotly/tests/test_optional/test_figure_factory.py index 5eff6b2c16a..03e9cbc6159 100644 --- a/plotly/tests/test_optional/test_figure_factory.py +++ b/plotly/tests/test_optional/test_figure_factory.py @@ -44,13 +44,60 @@ def test_unequal_data_label_length(self): self.assertRaises(PlotlyError, tls.FigureFactory.create_distplot, **kwargs) - def test_simple_distplot(self): + def test_simple_distplot_prob_density(self): # we should be able to create a single distplot with a simple dataset # and default kwargs dp = tls.FigureFactory.create_distplot(hist_data=[[1, 2, 2, 3]], - group_labels=['distplot']) + group_labels=['distplot'], + histnorm='probability density') + expected_dp_layout = {'barmode': 'overlay', + 'hovermode': 'closest', + 'legend': {'traceorder': 'reversed'}, + 'xaxis1': {'anchor': 'y2', 'domain': [0.0, 1.0], 'zeroline': False}, + 'yaxis1': {'anchor': 'free', 'domain': [0.35, 1], 'position': 0.0}, + 'yaxis2': {'anchor': 'x1', + 'domain': [0, 0.25], + 'dtick': 1, + 'showticklabels': False}} + self.assertEqual(dp['layout'], expected_dp_layout) + + expected_dp_data_hist = {'autobinx': False, + 'histnorm': 'probability density', + 'legendgroup': 'distplot', + 'marker': {'color': 'rgb(31, 119, 180)'}, + 'name': 'distplot', + 'opacity': 0.7, + 'type': 'histogram', + 'x': [1, 2, 2, 3], + 'xaxis': 'x1', + 'xbins': {'end': 3.0, 'size': 1.0, 'start': 1.0}, + 'yaxis': 'y1'} + self.assertEqual(dp['data'][0], expected_dp_data_hist) + + expected_dp_data_rug = {'legendgroup': 'distplot', + 'marker': {'color': 'rgb(31, 119, 180)', + 'symbol': 'line-ns-open'}, + 'mode': 'markers', + 'name': 'distplot', + 'showlegend': False, + 'text': None, + 'type': 'scatter', + 'x': [1, 2, 2, 3], + 'xaxis': 'x1', + 'y': ['distplot', 'distplot', + 'distplot', 'distplot'], + 'yaxis': 'y2'} + self.assertEqual(dp['data'][2], expected_dp_data_rug) + + def test_simple_distplot_prob(self): + + # we should be able to create a single distplot with a simple dataset + # and default kwargs + + dp = tls.FigureFactory.create_distplot(hist_data=[[1, 2, 2, 3]], + group_labels=['distplot'], histnorm='probability') expected_dp_layout = {'barmode': 'overlay', 'hovermode': 'closest', 'legend': {'traceorder': 'reversed'}, @@ -90,7 +137,7 @@ def test_simple_distplot(self): 'yaxis': 'y2'} self.assertEqual(dp['data'][2], expected_dp_data_rug) - def test_distplot_more_args(self): + def test_distplot_more_args_prob_dens(self): # we should be able to create a distplot with 2 datasets no # rugplot, defined bin_size, and added title @@ -106,6 +153,69 @@ def test_distplot_more_args(self): group_labels = ['2012', '2013'] dp = tls.FigureFactory.create_distplot(hist_data, group_labels, + histnorm='probability density', + show_rug=False, bin_size=.2) + dp['layout'].update(title='Dist Plot') + + expected_dp_layout = {'barmode': 'overlay', + 'hovermode': 'closest', + 'legend': {'traceorder': 'reversed'}, + 'title': 'Dist Plot', + 'xaxis1': {'anchor': 'y2', 'domain': [0.0, 1.0], + 'zeroline': False}, + 'yaxis1': {'anchor': 'free', 'domain': [0.0, 1], + 'position': 0.0}} + self.assertEqual(dp['layout'], expected_dp_layout) + + expected_dp_data_hist_1 = {'autobinx': False, + 'histnorm': 'probability density', + 'legendgroup': '2012', + 'marker': {'color': 'rgb(31, 119, 180)'}, + 'name': '2012', + 'opacity': 0.7, + 'type': 'histogram', + 'x': [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, -0.07, + 1.95, 0.9, -0.2, -0.5, 0.3, 0.4, + -0.37, 0.6], + 'xaxis': 'x1', + 'xbins': {'end': 1.95, 'size': 0.2, + 'start': -0.9}, + 'yaxis': 'y1'} + self.assertEqual(dp['data'][0], expected_dp_data_hist_1) + + expected_dp_data_hist_2 = {'autobinx': False, + 'histnorm': 'probability density', + 'legendgroup': '2013', + 'marker': {'color': 'rgb(255, 127, 14)'}, + 'name': '2013', + 'opacity': 0.7, + 'type': 'histogram', + 'x': [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, 0.8, + 1.7, 0.5, 0.8, -0.3, 1.2, 0.56, 0.3, + 2.2], + 'xaxis': 'x1', + 'xbins': {'end': 2.2, 'size': 0.2, + 'start': -0.3}, + 'yaxis': 'y1'} + self.assertEqual(dp['data'][1], expected_dp_data_hist_2) + + def test_distplot_more_args_prob(self): + + # we should be able to create a distplot with 2 datasets no + # rugplot, defined bin_size, and added title + + hist1_x = [0.8, 1.2, 0.2, 0.6, 1.6, + -0.9, -0.07, 1.95, 0.9, -0.2, + -0.5, 0.3, 0.4, -0.37, 0.6] + hist2_x = [0.8, 1.5, 1.5, 0.6, 0.59, + 1.0, 0.8, 1.7, 0.5, 0.8, + -0.3, 1.2, 0.56, 0.3, 2.2] + + hist_data = [hist1_x] + [hist2_x] + group_labels = ['2012', '2013'] + + dp = tls.FigureFactory.create_distplot(hist_data, group_labels, + histnorm='probability', show_rug=False, bin_size=.2) dp['layout'].update(title='Dist Plot') @@ -151,7 +261,55 @@ def test_distplot_more_args(self): 'yaxis': 'y1'} self.assertEqual(dp['data'][1], expected_dp_data_hist_2) - def test_distplot_binsize_array(self): + def test_distplot_binsize_array_prob(self): + hist1_x = [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, -0.07, 1.95, 0.9, -0.2, + -0.5, 0.3, 0.4, -0.37, 0.6] + hist2_x = [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, 0.8, 1.7, 0.5, 0.8, -0.3, + 1.2, 0.56, 0.3, 2.2] + + hist_data = [hist1_x, hist2_x] + group_labels = ['2012', '2013'] + + dp = tls.FigureFactory.create_distplot(hist_data, group_labels, + histnorm='probability', + show_rug=False, + bin_size=[.2, .2]) + + expected_dp_data_hist_1 = {'autobinx': False, + 'histnorm': 'probability density', + 'legendgroup': '2012', + 'marker': + {'color': 'rgb(31, 119, 180)'}, + 'name': '2012', + 'opacity': 0.7, + 'type': 'histogram', + 'x': [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, + -0.07, 1.95, 0.9, -0.2, -0.5, 0.3, + 0.4, -0.37, 0.6], + 'xaxis': 'x1', + 'xbins': {'end': 1.95, 'size': 0.2, + 'start': -0.9}, + 'yaxis': 'y1'} + self.assertEqual(dp['data'][0], expected_dp_data_hist_1) + + expected_dp_data_hist_2 = {'autobinx': False, + 'histnorm': 'probability density', + 'legendgroup': '2013', + 'marker': + {'color': 'rgb(255, 127, 14)'}, + 'name': '2013', + 'opacity': 0.7, + 'type': 'histogram', + 'x': [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, + 0.8, 1.7, 0.5, 0.8, -0.3, 1.2, + 0.56, 0.3, 2.2], + 'xaxis': 'x1', + 'xbins': {'end': 2.2, 'size': 0.2, + 'start': -0.3}, + 'yaxis': 'y1'} + self.assertEqual(dp['data'][1], expected_dp_data_hist_2) + + def test_distplot_binsize_array_prob_density(self): hist1_x = [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, -0.07, 1.95, 0.9, -0.2, -0.5, 0.3, 0.4, -0.37, 0.6] hist2_x = [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, 0.8, 1.7, 0.5, 0.8, -0.3, @@ -161,19 +319,21 @@ def test_distplot_binsize_array(self): group_labels = ['2012', '2013'] dp = tls.FigureFactory.create_distplot(hist_data, group_labels, + histnorm='probability', show_rug=False, bin_size=[.2, .2]) expected_dp_data_hist_1 = {'autobinx': False, - 'histnorm': 'probability', + 'histnorm': 'probability density', 'legendgroup': '2012', - 'marker': {'color': 'rgb(31, 119, 180)'}, + 'marker': + {'color': 'rgb(31, 119, 180)'}, 'name': '2012', 'opacity': 0.7, 'type': 'histogram', - 'x': [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, -0.07, - 1.95, 0.9, -0.2, -0.5, 0.3, 0.4, - -0.37, 0.6], + 'x': [0.8, 1.2, 0.2, 0.6, 1.6, -0.9, + -0.07, 1.95, 0.9, -0.2, -0.5, 0.3, + 0.4, -0.37, 0.6], 'xaxis': 'x1', 'xbins': {'end': 1.95, 'size': 0.2, 'start': -0.9}, @@ -181,15 +341,16 @@ def test_distplot_binsize_array(self): self.assertEqual(dp['data'][0], expected_dp_data_hist_1) expected_dp_data_hist_2 = {'autobinx': False, - 'histnorm': 'probability', + 'histnorm': 'probability density', 'legendgroup': '2013', - 'marker': {'color': 'rgb(255, 127, 14)'}, + 'marker': + {'color': 'rgb(255, 127, 14)'}, 'name': '2013', 'opacity': 0.7, 'type': 'histogram', - 'x': [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, 0.8, - 1.7, 0.5, 0.8, -0.3, 1.2, 0.56, 0.3, - 2.2], + 'x': [0.8, 1.5, 1.5, 0.6, 0.59, 1.0, + 0.8, 1.7, 0.5, 0.8, -0.3, 1.2, + 0.56, 0.3, 2.2], 'xaxis': 'x1', 'xbins': {'end': 2.2, 'size': 0.2, 'start': -0.3}, diff --git a/plotly/tools.py b/plotly/tools.py index 0f71d950e85..b02daa4d6ea 100644 --- a/plotly/tools.py +++ b/plotly/tools.py @@ -28,6 +28,9 @@ 'rgb(227, 119, 194)', 'rgb(127, 127, 127)', 'rgb(188, 189, 34)', 'rgb(23, 190, 207)'] +DEFAULT_HISTNORM = 'probability density' +ALTERNATIVE_HISTNORM = 'probability' + # Warning format def warning_on_one_line(message, category, filename, lineno, @@ -4019,7 +4022,7 @@ def create_candlestick(open, high, low, close, @staticmethod def create_distplot(hist_data, group_labels, bin_size=1., curve_type='kde', - colors=[], rug_text=[], + colors=[], rug_text=[], histnorm=DEFAULT_HISTNORM, show_hist=True, show_curve=True, show_rug=True): """ @@ -4036,6 +4039,8 @@ def create_distplot(hist_data, group_labels, :param (list[float]|float) bin_size: Size of histogram bins. Default = 1. :param (str) curve_type: 'kde' or 'normal'. Default = 'kde' + :param (str) histnorm: 'probability density' or 'probability' + Default = 'probability density' :param (bool) show_hist: Add histogram to distplot? Default = True :param (bool) show_curve: Add curve to distplot? Default = True :param (bool) show_rug: Add rug to distplot? Default = True @@ -4144,23 +4149,23 @@ def create_distplot(hist_data, group_labels, bin_size = [bin_size]*len(hist_data) hist = _Distplot( - hist_data, group_labels, bin_size, + hist_data, histnorm, group_labels, bin_size, curve_type, colors, rug_text, show_hist, show_curve).make_hist() if curve_type == 'normal': curve = _Distplot( - hist_data, group_labels, bin_size, + hist_data, histnorm, group_labels, bin_size, curve_type, colors, rug_text, show_hist, show_curve).make_normal() else: curve = _Distplot( - hist_data, group_labels, bin_size, + hist_data, histnorm, group_labels, bin_size, curve_type, colors, rug_text, show_hist, show_curve).make_kde() rug = _Distplot( - hist_data, group_labels, bin_size, + hist_data, histnorm, group_labels, bin_size, curve_type, colors, rug_text, show_hist, show_curve).make_rug() @@ -5036,10 +5041,11 @@ class _Distplot(FigureFactory): """ Refer to TraceFactory.create_distplot() for docstring """ - def __init__(self, hist_data, group_labels, + def __init__(self, hist_data, histnorm, group_labels, bin_size, curve_type, colors, rug_text, show_hist, show_curve): self.hist_data = hist_data + self.histnorm = histnorm self.group_labels = group_labels self.bin_size = bin_size self.show_hist = show_hist @@ -5081,7 +5087,7 @@ def make_hist(self): x=self.hist_data[index], xaxis='x1', yaxis='y1', - histnorm='probability', + histnorm=self.histnorm, name=self.group_labels[index], legendgroup=self.group_labels[index], marker=dict(color=self.colors[index]), @@ -5108,7 +5114,9 @@ def make_kde(self): self.curve_y[index] = (scipy.stats.gaussian_kde (self.hist_data[index]) (self.curve_x[index])) - self.curve_y[index] *= self.bin_size[index] + + if self.histnorm == ALTERNATIVE_HISTNORM: + self.curve_y[index] *= self.bin_size[index] for index in range(self.trace_number): curve[index] = dict(type='scatter', @@ -5143,7 +5151,9 @@ def make_normal(self): / 500 for x in range(500)] self.curve_y[index] = scipy.stats.norm.pdf( self.curve_x[index], loc=mean[index], scale=sd[index]) - self.curve_y[index] *= self.bin_size[index] + + if self.histnorm == ALTERNATIVE_HISTNORM: + self.curve_y[index] *= self.bin_size[index] for index in range(self.trace_number): curve[index] = dict(type='scatter', @@ -5621,4 +5631,3 @@ def make_table_annotations(self): font=dict(color=font_color), showarrow=False)) return annotations -