Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 79c67c7

Browse filesBrowse files
committed
finished chris comments and updated tests
1 parent 6da599f commit 79c67c7
Copy full SHA for 79c67c7

File tree

Expand file treeCollapse file tree

2 files changed

+114
-59
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+114
-59
lines changed

‎plotly/figure_factory/_bullet.py

Copy file name to clipboardExpand all lines: plotly/figure_factory/_bullet.py
+103-42Lines changed: 103 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
pd = optional_imports.get_module('pandas')
1212

13-
VALID_KEYS = ['title', 'subtitle', 'ranges', 'measures', 'markers']
1413

15-
16-
def _bullet(df, markers, measures, ranges, subtitle, title, orientation,
14+
def _bullet(df, markers, measures, ranges, subtitles, titles, orientation,
1715
range_colors, measure_colors, horizontal_spacing,
18-
vertical_spacing, scatter_options):
16+
vertical_spacing, scatter_options, layout_options):
17+
1918
num_of_lanes = len(df)
2019
num_of_rows = num_of_lanes if orientation == 'h' else 1
2120
num_of_cols = 1 if orientation == 'h' else num_of_lanes
@@ -30,11 +29,18 @@ def _bullet(df, markers, measures, ranges, subtitle, title, orientation,
3029
# layout
3130
fig['layout'].update(
3231
dict(shapes=[]),
32+
title='Bullet Chart',
33+
height=600,
34+
width=1000,
3335
showlegend=False,
3436
barmode='stack',
37+
annotations=[],
3538
margin=dict(l=120 if orientation == 'h' else 80),
3639
)
3740

41+
# update layout
42+
fig['layout'].update(layout_options)
43+
3844
if orientation == 'h':
3945
width_axis = 'yaxis'
4046
length_axis = 'xaxis'
@@ -120,22 +126,23 @@ def _bullet(df, markers, measures, ranges, subtitle, title, orientation,
120126
markers = go.Scatter(
121127
x=x,
122128
y=y,
123-
marker=dict(
124-
color='rgb(0, 0, 0)',
125-
symbol=marker_symbol,
126-
size=marker_size
127-
),
129+
marker=scatter_options['marker'],
128130
name='markers',
129131
hoverinfo='x' if orientation == 'h' else 'y',
130132
xaxis='x{}'.format(row + 1),
131133
yaxis='y{}'.format(row + 1)
132134
)
135+
136+
for k in scatter_options:
137+
if k != 'marker':
138+
markers[k] = scatter_options[k]
139+
133140
fig['data'].append(markers)
134141

135-
# labels
136-
title = df.iloc[row]['title']
137-
if 'subtitle' in df:
138-
subtitle = '<br>{}'.format(df.iloc[row]['subtitle'])
142+
# titles and subtitles
143+
title = df.iloc[row]['titles']
144+
if 'subtitles' in df:
145+
subtitle = '<br>{}'.format(df.iloc[row]['subtitles'])
139146
else:
140147
subtitle = ''
141148
label = '<b>{}</b>'.format(title) + subtitle
@@ -154,16 +161,29 @@ def _bullet(df, markers, measures, ranges, subtitle, title, orientation,
154161

155162

156163
def create_bullet(data, markers=None, measures=None, ranges=None,
157-
subtitle=None, title=None, orientation='h',
158-
range_colors=None, measure_colors=None, horizontal_spacing=None,
159-
vertical_spacing=None, chart_title='Bullet Chart',
160-
height=600, width=1000, **scatter_options):
164+
subtitles=None, titles=None, orientation='h',
165+
range_colors=None, measure_colors=None,
166+
horizontal_spacing=None, vertical_spacing=None,
167+
scatter_options={}, **layout_options):
161168
"""
162169
Returns figure for bullet chart.
163170
164171
:param (pd.DataFrame | list) data: either a JSON list of dicts or a pandas
165-
DataFrame. All keys must be one of 'title', 'subtitle', 'ranges',
166-
'measures', and 'markers'.
172+
DataFrame.
173+
:param (str) markers: the column name or dictionary key for the markers in
174+
each subplot.
175+
:param (str) measures: the column name or dictionary key for the measure
176+
bars in each subplot. This bar usually represents the quantitative
177+
measure of performance, usually a list of two values [a, b] and are
178+
the blue bars in the foreground of each subplot by default.
179+
:param (str) ranges: the column name or dictionary key for the qualitative
180+
ranges of performance, usually a 3-item list [bad, okay, good]. They
181+
correspond to the grey bars in the background of each chart.
182+
:param (str) subtitles: the column name or dictionary key for the subtitle
183+
of each subplot chart. The subplots are displayed right underneath
184+
each title.
185+
:param (str) titles: the column name or dictionary key for the main label
186+
of each subplot chart.
167187
:param (bool) orientation: if 'h', the bars are placed horizontally as
168188
rows. If 'v' the bars are placed vertically in the chart.
169189
:param (int) marker_size: sets the size of the markers in the chart.
@@ -181,9 +201,55 @@ def create_bullet(data, markers=None, measures=None, ranges=None,
181201
plotly.tools.make_subplots. Ranges between 0 and 1.
182202
:param (float) vertical_spacing: see the 'vertical_spacing' param in
183203
plotly.tools.make_subplots. Ranges between 0 and 1.
184-
:param (str) title: title of the bullet chart.
185-
:param (float) height: height of the chart.
186-
:param (float) width width of the chart.
204+
:param (dict) scatter_options: describes attributes for the scatter trace
205+
in each subplot such as name and marker size. Call
206+
help(plotly.graph_objs.Scatter) for more information on valid params.
207+
:param layout_options: describes attributes for the layout of the figure
208+
such as title, height and width. Call help(plotly.graph_objs.Layout)
209+
for more information on valid params.
210+
211+
Example 1: Use a Dictionary
212+
```
213+
import plotly
214+
import plotly.plotly as py
215+
import plotly.figure_factory as ff
216+
217+
data = [
218+
{"e": "Revenue", "d": "US$, in thousands", "c": [150, 225, 300],
219+
"b": [220,270], "a": [250]},
220+
{"e": "Profit", "d": "%", "c": [20, 25, 30], "b": [21, 23], "a": [26]},
221+
{"e": "Order Size", "d":"US$, average","c": [350, 500, 600],
222+
"b": [100,320],"a": [550]},
223+
{"e": "New Customers", "d": "count", "c": [1400, 2000, 2500],
224+
"b": [1000,1650],"a": [2100]},
225+
{"e": "Satisfaction", "d": "out of 5","c": [3.5, 4.25, 5],
226+
"b": [3.2,4.7], "a": [4.4]}
227+
]
228+
229+
fig = ff.create_bullet(
230+
data, titles='e', subtitles='d', markers='a', measures='b',
231+
ranges='c', orientation='h', title='my simple bullet chart'
232+
)
233+
py.iplot(fig)
234+
```
235+
236+
Example 2: Use a DataFrame with Custom Colors
237+
```
238+
import plotly.plotly as py
239+
import plotly.figure_factory as ff
240+
241+
import pandas as pd
242+
243+
data = pd.read_json('https://cdn.rawgit.com/plotly/datasets/master/BulletData.json')
244+
245+
fig = ff.create_bullet(
246+
data, titles='title', markers='markers', measures='measures',
247+
orientation='v', measure_colors=['rgb(14, 52, 75)', 'rgb(31, 141, 127)'],
248+
scatter_options={'marker': {'symbol': 'circle'}}, width=700
249+
250+
)
251+
py.iplot(fig)
252+
```
187253
"""
188254
# validate df
189255
if not pd:
@@ -203,12 +269,12 @@ def create_bullet(data, markers=None, measures=None, ranges=None,
203269
)
204270

205271
# make DataFrame from data with correct column headers
206-
col_names = ['title', 'subtitle', 'markers', 'measures', 'ranges']
272+
col_names = ['titles', 'subtitle', 'markers', 'measures', 'ranges']
207273
if isinstance(data, list):
208274
df = pd.DataFrame(
209275
[
210-
[d[title] for d in data] if title else [''] * len(data),
211-
[d[subtitle] for d in data] if subtitle else [''] * len(data),
276+
[d[titles] for d in data] if titles else [''] * len(data),
277+
[d[subtitles] for d in data] if subtitles else [''] * len(data),
212278
[d[markers] for d in data] if markers else [[]] * len(data),
213279
[d[measures] for d in data] if measures else [[]] * len(data),
214280
[d[ranges] for d in data] if ranges else [[]] * len(data),
@@ -218,8 +284,8 @@ def create_bullet(data, markers=None, measures=None, ranges=None,
218284
elif isinstance(data, pd.DataFrame):
219285
df = pd.DataFrame(
220286
[
221-
data[title].tolist() if title else [''] * len(data),
222-
data[subtitle].tolist() if subtitle else [''] * len(data),
287+
data[titles].tolist() if titles else [''] * len(data),
288+
data[subtitles].tolist() if subtitles else [''] * len(data),
223289
data[markers].tolist() if markers else [[]] * len(data),
224290
data[measures].tolist() if measures else [[]] * len(data),
225291
data[ranges].tolist() if ranges else [[]] * len(data),
@@ -250,30 +316,25 @@ def create_bullet(data, markers=None, measures=None, ranges=None,
250316
colors_list = colors.convert_colors_to_same_type(colors_list,
251317
'rgb')[0]
252318

253-
# scatter options
254-
default_scatter_options = {
319+
# default scatter options
320+
default_scatter = {
255321
'marker': {'size': 12,
256322
'symbol': 'diamond-tall',
257323
'color': 'rgb(0, 0, 0)'}
258324
}
325+
259326
if scatter_options == {}:
260-
scatter_options.update(default_scatter_options)
327+
scatter_options.update(default_scatter)
261328
else:
262-
263-
264-
265-
329+
# add default options to scatter_options if they are not present
330+
for k in default_scatter['marker']:
331+
if k not in scatter_options['marker']:
332+
scatter_options['marker'][k] = default_scatter['marker'][k]
266333

267334
fig = _bullet(
268-
df, markers, measures, ranges, subtitle, title, orientation,
335+
df, markers, measures, ranges, subtitles, titles, orientation,
269336
range_colors, measure_colors, horizontal_spacing, vertical_spacing,
270-
scatter_options
271-
)
272-
273-
fig['layout'].update(
274-
title=chart_title,
275-
height=height,
276-
width=width,
337+
scatter_options, layout_options,
277338
)
278339

279340
return fig

‎plotly/tests/test_optional/test_figure_factory.py

Copy file name to clipboardExpand all lines: plotly/tests/test_optional/test_figure_factory.py
+11-17Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,7 +2189,7 @@ class TestBullet(NumpyTestUtilsMixin, TestCase):
21892189

21902190
def test_df_as_list(self):
21912191
df = [
2192-
{'title': 'Revenue'},
2192+
{'titles': 'Revenue'},
21932193
'foo'
21942194
]
21952195

@@ -2202,15 +2202,6 @@ def test_not_df_or_list(self):
22022202
pattern = ('You must input a pandas DataFrame or a list of dictionaries.')
22032203
self.assertRaisesRegexp(PlotlyError, pattern, ff.create_bullet, df)
22042204

2205-
def test_valid_keys(self):
2206-
df = [{'title': 'Revenue', 'foo': 'bar'}]
2207-
VALID_KEYS = ['title', 'subtitle', 'ranges', 'measures', 'markers']
2208-
2209-
pattern = (
2210-
'Your headers/dict keys must be either {}'
2211-
).format(utils.list_of_options(VALID_KEYS, 'or'))
2212-
self.assertRaisesRegexp(PlotlyError, pattern, ff.create_bullet, df)
2213-
22142205
def test_valid_color_lists_of_2_rgb_colors(self):
22152206
df = [
22162207
{'title': 'Revenue'}
@@ -2238,9 +2229,12 @@ def test_full_bullet(self):
22382229
range_colors = ['rgb(255, 127, 14)', 'rgb(44, 160, 44)']
22392230

22402231
fig = ff.create_bullet(
2241-
df, as_rows=False, marker_size=30, marker_symbol='hourglass',
2232+
df, orientation='v', markers='markers', measures='measures',
2233+
ranges='ranges', subtitles='subtitle', titles='title',
22422234
range_colors=range_colors, measure_colors=measure_colors,
2243-
title='new title'
2235+
title='new title',
2236+
scatter_options={'marker': {'size': 30,
2237+
'symbol': 'hourglass'}}
22442238
)
22452239

22462240
exp_fig = {
@@ -2571,7 +2565,7 @@ def test_full_bullet(self):
25712565
'yaxis': 'y5'}],
25722566
'layout': {'annotations': [{'font': {'color': '#0f0f0f', 'size': 13},
25732567
'showarrow': False,
2574-
'text': '<b>Revenue</b><br>US$, in thousands',
2568+
'text': '<b>Revenue</b>',
25752569
'textangle': 0,
25762570
'x': 0.019999999999999997,
25772571
'xanchor': 'center',
@@ -2581,7 +2575,7 @@ def test_full_bullet(self):
25812575
'yref': 'paper'},
25822576
{'font': {'color': '#0f0f0f', 'size': 13},
25832577
'showarrow': False,
2584-
'text': '<b>Profit</b><br>%',
2578+
'text': '<b>Profit</b>',
25852579
'textangle': 0,
25862580
'x': 0.26,
25872581
'xanchor': 'center',
@@ -2591,7 +2585,7 @@ def test_full_bullet(self):
25912585
'yref': 'paper'},
25922586
{'font': {'color': '#0f0f0f', 'size': 13},
25932587
'showarrow': False,
2594-
'text': '<b>Order Size</b><br>US$, average',
2588+
'text': '<b>Order Size</b>',
25952589
'textangle': 0,
25962590
'x': 0.5,
25972591
'xanchor': 'center',
@@ -2601,7 +2595,7 @@ def test_full_bullet(self):
26012595
'yref': 'paper'},
26022596
{'font': {'color': '#0f0f0f', 'size': 13},
26032597
'showarrow': False,
2604-
'text': '<b>New Customers</b><br>count',
2598+
'text': '<b>New Customers</b>',
26052599
'textangle': 0,
26062600
'x': 0.74,
26072601
'xanchor': 'center',
@@ -2611,7 +2605,7 @@ def test_full_bullet(self):
26112605
'yref': 'paper'},
26122606
{'font': {'color': '#0f0f0f', 'size': 13},
26132607
'showarrow': False,
2614-
'text': '<b>Satisfaction</b><br>out of 5',
2608+
'text': '<b>Satisfaction</b>',
26152609
'textangle': 0,
26162610
'x': 0.98,
26172611
'xanchor': 'center',

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.