10
10
11
11
pd = optional_imports .get_module ('pandas' )
12
12
13
- SUBPLOT_SPACING = 0.015
14
13
VALID_KEYS = ['title' , 'subtitle' , 'ranges' , 'measures' , 'markers' ]
15
14
16
15
17
- # add shapes
18
- def rectangle (color , x0 , x1 , y0 , y1 , xref , yref , layer ):
19
- return {
20
- 'fillcolor' : color ,
21
- 'line' : {'width' : 0 },
22
- 'opacity' : 1 ,
23
- 'type' : 'rect' ,
24
- 'x0' : x0 ,
25
- 'x1' : x1 ,
26
- 'xref' : xref ,
27
- 'y0' : y0 ,
28
- 'y1' : y1 ,
29
- 'yref' : yref ,
30
- 'layer' : layer
31
- }
32
-
33
-
34
16
def _bullet (df , as_rows , marker_size , marker_symbol , range_colors ,
35
- measure_colors ):
17
+ measure_colors , subplot_spacing ):
36
18
num_of_lanes = len (df )
37
19
num_of_rows = num_of_lanes if as_rows else 1
38
20
num_of_cols = 1 if as_rows else num_of_lanes
21
+ if not subplot_spacing :
22
+ subplot_spacing = 1. / num_of_lanes
39
23
fig = plotly .tools .make_subplots (
40
24
num_of_rows , num_of_cols , print_grid = False ,
41
- horizontal_spacing = SUBPLOT_SPACING ,
42
- vertical_spacing = SUBPLOT_SPACING
25
+ horizontal_spacing = subplot_spacing ,
26
+ vertical_spacing = subplot_spacing
43
27
)
44
28
45
29
# layout
46
30
fig ['layout' ].update (
47
31
dict (shapes = []),
48
32
showlegend = False ,
49
- annotations = [] ,
33
+ barmode = 'stack' ,
50
34
margin = dict (l = 120 if as_rows else 80 ),
51
35
)
52
36
53
37
if as_rows :
54
- length_axis = 'xaxis'
55
38
width_axis = 'yaxis'
39
+ length_axis = 'xaxis'
56
40
else :
57
41
width_axis = 'xaxis'
58
42
length_axis = 'yaxis'
@@ -67,105 +51,102 @@ def _bullet(df, as_rows, marker_size, marker_symbol, range_colors,
67
51
fig ['layout' ][key ]['showticklabels' ] = False
68
52
fig ['layout' ][key ]['range' ] = [0 , 1 ]
69
53
54
+ # narrow domain if 1 bar
55
+ if num_of_lanes <= 1 :
56
+ fig ['layout' ][width_axis + '1' ]['domain' ] = [0.4 , 0.6 ]
57
+
70
58
# marker symbol size
71
59
if not marker_size :
72
- if num_of_lanes <= 3 :
60
+ if num_of_lanes <= 4 :
73
61
marker_size = 18
74
62
else :
75
- marker_size = 12
76
- for idx in range (num_of_lanes ):
77
- # marker
78
- x = df .iloc [idx ]['markers' ] if as_rows else [0.5 ]
79
- y = [0.5 ] if as_rows else df .iloc [idx ]['markers' ]
80
- fig ['data' ].append (
81
- go .Scatter (
63
+ marker_size = 8
64
+
65
+ if not range_colors :
66
+ range_colors = ['rgb(200, 200, 200)' , 'rgb(245, 245, 245)' ]
67
+ if not measure_colors :
68
+ measure_colors = ['rgb(31, 119, 180)' , 'rgb(176, 196, 221)' ]
69
+
70
+ for row in range (num_of_lanes ):
71
+ # ranges bars
72
+ for idx in range (len (df .iloc [row ]['ranges' ])):
73
+ inter_colors = colors .n_colors (
74
+ range_colors [0 ], range_colors [1 ],
75
+ len (df .iloc [row ]['ranges' ]), 'rgb'
76
+ )
77
+ x = [sorted (df .iloc [row ]['ranges' ])[- 1 - idx ]] if as_rows else [0 ]
78
+ y = [0 ] if as_rows else [sorted (df .iloc [row ]['ranges' ])[- 1 - idx ]]
79
+ bar = go .Bar (
82
80
x = x ,
83
81
y = y ,
84
82
marker = dict (
85
- size = marker_size ,
86
- color = 'rgb(0, 0, 0)' ,
87
- symbol = marker_symbol
83
+ color = inter_colors [- 1 - idx ]
88
84
),
89
- xaxis = 'x{}' .format (idx + 1 ),
90
- yaxis = 'y{}' .format (idx + 1 )
85
+ name = 'ranges' ,
86
+ hoverinfo = 'x' if as_rows else 'y' ,
87
+ orientation = 'h' if as_rows else 'v' ,
88
+ width = 2 ,
89
+ base = 0 ,
90
+ xaxis = 'x{}' .format (row + 1 ),
91
+ yaxis = 'y{}' .format (row + 1 )
91
92
)
92
- )
93
+ fig [ 'data' ]. append ( bar )
93
94
94
- # ranges
95
- y0_ranges = 0.35
96
- y1_ranges = 0.65
97
- if not range_colors :
98
- range_colors = ['rgb(200, 200, 200)' , 'rgb(245, 245, 245)' ]
99
- ranges_len = len (df .iloc [idx ]['ranges' ])
100
- if ranges_len <= 1 :
101
- inter_colors = [range_colors [0 ]]
102
- else :
95
+ # measures bars
96
+ for idx in range (len (df .iloc [row ]['measures' ])):
103
97
inter_colors = colors .n_colors (
104
- range_colors [0 ], range_colors [1 ], ranges_len , 'rgb'
105
- )
106
- for range_idx in range (ranges_len ):
107
- color = inter_colors [range_idx ]
108
- if range_idx == 0 :
109
- start_range = 0
110
- else :
111
- start_range = df .iloc [idx ]['ranges' ][range_idx - 1 ]
112
- end_range = df .iloc [idx ]['ranges' ][range_idx ]
113
-
114
- x0 = start_range if as_rows else y0_ranges
115
- x1 = end_range if as_rows else y1_ranges
116
- y0 = y0_ranges if as_rows else start_range
117
- y1 = y1_ranges if as_rows else end_range
118
- fig ['layout' ]['shapes' ].append (
119
- rectangle (
120
- color , x0 , x1 , y0 , y1 ,
121
- 'x{}' .format (idx + 1 ),
122
- 'y{}' .format (idx + 1 ),
123
- 'below'
124
- )
98
+ measure_colors [0 ], measure_colors [1 ],
99
+ len (df .iloc [row ]['measures' ]), 'rgb'
125
100
)
126
-
127
- # measures
128
- y0_measures = 0.45
129
- y1_measures = 0.55
130
- if not measure_colors :
131
- measure_colors = ['rgb(31, 119, 180)' , 'rgb(176, 196, 221)' ]
132
- measures_len = len (df .iloc [idx ]['measures' ])
133
- if measures_len <= 1 :
134
- inter_colors = [measure_colors [0 ]]
135
- else :
136
- inter_colors = colors .n_colors (
137
- measure_colors [0 ], measure_colors [1 ], measures_len , 'rgb'
101
+ x = ([sorted (df .iloc [row ]['measures' ])[- 1 - idx ]] if as_rows
102
+ else [0.5 ])
103
+ y = ([0.5 ] if as_rows
104
+ else [sorted (df .iloc [row ]['measures' ])[- 1 - idx ]])
105
+ bar = go .Bar (
106
+ x = x ,
107
+ y = y ,
108
+ marker = dict (
109
+ color = inter_colors [- 1 - idx ]
110
+ ),
111
+ name = 'measures' ,
112
+ hoverinfo = 'x' if as_rows else 'y' ,
113
+ orientation = 'h' if as_rows else 'v' ,
114
+ width = 0.4 ,
115
+ base = 0 ,
116
+ xaxis = 'x{}' .format (row + 1 ),
117
+ yaxis = 'y{}' .format (row + 1 )
138
118
)
139
- for range_idx in range (measures_len ):
140
- color = inter_colors [range_idx ]
141
- if range_idx == 0 :
142
- start_range = 0
143
- else :
144
- start_range = df .iloc [idx ]['measures' ][range_idx - 1 ]
145
- end_range = df .iloc [idx ]['measures' ][range_idx ]
119
+ fig ['data' ].append (bar )
146
120
147
- x0 = start_range if as_rows else y0_measures
148
- x1 = end_range if as_rows else y1_measures
149
- y0 = y0_measures if as_rows else start_range
150
- y1 = y1_measures if as_rows else end_range
151
- fig ['layout' ]['shapes' ].append (
152
- rectangle (
153
- color , x0 , x1 , y0 , y1 ,
154
- 'x{}' .format (idx + 1 ),
155
- 'y{}' .format (idx + 1 ),
156
- 'below'
157
- )
158
- )
121
+ # markers
122
+ x = df .iloc [row ]['markers' ] if as_rows else [0.5 ]
123
+ y = [0.5 ] if as_rows else df .iloc [row ]['markers' ]
124
+ markers = go .Scatter (
125
+ x = x ,
126
+ y = y ,
127
+ marker = dict (
128
+ color = 'rgb(0, 0, 0)' ,
129
+ symbol = marker_symbol ,
130
+ size = marker_size
131
+ ),
132
+ name = 'markers' ,
133
+ hoverinfo = 'x' if as_rows else 'y' ,
134
+ xaxis = 'x{}' .format (row + 1 ),
135
+ yaxis = 'y{}' .format (row + 1 )
136
+ )
137
+ fig ['data' ].append (markers )
159
138
160
139
# labels
161
- title = df .iloc [idx ]['title' ]
140
+ title = df .iloc [row ]['title' ]
162
141
if 'subtitle' in df :
163
- subtitle = '<br>{}' .format (df .iloc [idx ]['subtitle' ])
142
+ subtitle = '<br>{}' .format (df .iloc [row ]['subtitle' ])
164
143
else :
165
144
subtitle = ''
166
145
label = '<b>{}</b>' .format (title ) + subtitle
167
146
annot = utils .annotation_dict_for_label (
168
- label , num_of_lanes - idx , num_of_lanes , SUBPLOT_SPACING ,
147
+ label ,
148
+ (num_of_lanes - row if as_rows else row + 1 ),
149
+ num_of_lanes , subplot_spacing ,
169
150
'row' if as_rows else 'col' ,
170
151
True if as_rows else False ,
171
152
False
@@ -177,8 +158,8 @@ def _bullet(df, as_rows, marker_size, marker_symbol, range_colors,
177
158
178
159
def create_bullet (df , as_rows = True , marker_size = 16 ,
179
160
marker_symbol = 'diamond-tall' , range_colors = None ,
180
- measure_colors = None , title = 'Bullet Chart' , height = 600 ,
181
- width = 1000 ):
161
+ measure_colors = None , subplot_spacing = None ,
162
+ title = 'Bullet Chart' , height = 600 , width = 1000 ):
182
163
"""
183
164
Returns figure for bullet chart.
184
165
@@ -198,6 +179,9 @@ def create_bullet(df, as_rows=True, marker_size=16,
198
179
:param (list) measure_colors: a list of two colors which is used to color
199
180
the thin quantitative bars in the bullet chart.
200
181
Default=['rgb(31, 119, 180)', 'rgb(176, 196, 221)']
182
+ :param (float) subplot_spacing: set the distance between each bar chart.
183
+ If not specified an automatic spacing is assigned based on the number
184
+ of bars to be plotted.
201
185
:param (str) title: title of the bullet chart.
202
186
:param (float) height: height of the chart.
203
187
:param (float) width width of the chart.
@@ -260,7 +244,8 @@ def create_bullet(df, as_rows=True, marker_size=16,
260
244
'rgb' )[0 ]
261
245
262
246
fig = _bullet (
263
- df , as_rows , marker_size , marker_symbol , range_colors , measure_colors
247
+ df , as_rows , marker_size , marker_symbol , range_colors , measure_colors ,
248
+ subplot_spacing
264
249
)
265
250
266
251
fig ['layout' ].update (
0 commit comments