0001-dataviz-add-stacked-bar-percent-chart-type-52845.patch
combo/apps/dataviz/migrations/0011_auto_20200813_1100.py | ||
---|---|---|
45 | 45 |
('bar', 'Bar'), |
46 | 46 |
('horizontal-bar', 'Horizontal Bar'), |
47 | 47 |
('stacked-bar', 'Stacked Bar'), |
48 |
('stacked-bar-percent', 'Stacked Bar (%)'), |
|
48 | 49 |
('line', 'Line'), |
49 | 50 |
('pie', 'Pie'), |
50 | 51 |
('dot', 'Dot'), |
combo/apps/dataviz/models.py | ||
---|---|---|
190 | 190 |
('bar', _('Bar')), |
191 | 191 |
('horizontal-bar', _('Horizontal Bar')), |
192 | 192 |
('stacked-bar', _('Stacked Bar')), |
193 |
('stacked-bar-percent', _('Stacked Bar (%)')), |
|
193 | 194 |
('line', _('Line')), |
194 | 195 |
('pie', _('Pie')), |
195 | 196 |
('dot', _('Dot')), |
... | ... | |
306 | 307 |
'bar': pygal.Bar, |
307 | 308 |
'horizontal-bar': pygal.HorizontalBar, |
308 | 309 |
'stacked-bar': pygal.StackedBar, |
310 |
'stacked-bar-percent': pygal.StackedBar, |
|
309 | 311 |
'line': pygal.Line, |
310 | 312 |
'pie': pygal.Pie, |
311 | 313 |
'dot': pygal.Dot, |
... | ... | |
337 | 339 |
if data |
338 | 340 |
] |
339 | 341 | |
342 |
if self.chart_type == 'stacked-bar-percent': |
|
343 |
self.make_percent([serie['data'] for serie in data['series']]) |
|
344 | ||
340 | 345 |
for serie in data['series']: |
341 | 346 |
chart.add(serie['label'], serie['data']) |
342 | 347 | |
... | ... | |
485 | 490 | |
486 | 491 |
def add_data_to_chart(self, chart, data, y_labels): |
487 | 492 |
if self.chart_type != 'pie': |
493 |
series_data = [] |
|
488 | 494 |
for i, serie_label in enumerate(y_labels): |
489 | 495 |
if chart.axis_count < 2: |
490 | 496 |
values = data |
491 | 497 |
else: |
492 | 498 |
values = [data[i][j] for j in range(len(chart.x_labels))] |
499 |
series_data.append(values) |
|
493 | 500 |
chart.add(serie_label, values) |
501 |
if self.chart_type == 'stacked-bar-percent': |
|
502 |
self.make_percent(series_data) |
|
494 | 503 |
else: |
495 | 504 |
# pie, create a serie by data, to get different colours |
496 | 505 |
values = data |
... | ... | |
529 | 538 |
elif measure == 'percent': |
530 | 539 |
percent_formatter = lambda x: '{:.1f}%'.format(x) |
531 | 540 |
return percent_formatter |
541 | ||
542 |
def make_percent(self, series_data): |
|
543 |
for i, values in enumerate(zip(*series_data)): |
|
544 |
sum_values = sum([v for v in values if v is not None]) |
|
545 |
if sum_values == 0: |
|
546 |
continue |
|
547 | ||
548 |
factor = 100 / sum_values |
|
549 |
for values in series_data: |
|
550 |
if values[i] is not None: |
|
551 |
values[i] = round(values[i] * factor, 1) |
tests/test_dataviz.py | ||
---|---|---|
441 | 441 |
([122, 114, 2, 33], {'title': u'bar'}), |
442 | 442 |
] |
443 | 443 | |
444 |
# stacked bar with percent |
|
445 |
cell.chart_type = 'stacked-bar-percent' |
|
446 |
cell.save() |
|
447 | ||
448 |
chart = cell.get_chart() |
|
449 |
assert chart.x_labels == ['web', 'mail', 'phone', 'email'] |
|
450 |
assert chart.raw_series == [ |
|
451 |
([64.5, 54, 0, 61.6], {'title': u'foo'}), |
|
452 |
([35.5, 46, 100, 38.4], {'title': u'bar'}), |
|
453 |
] |
|
454 |
assert all(x + y == 100 for x, y in zip(chart.raw_series[0][0], chart.raw_series[1][0])) |
|
455 | ||
444 | 456 |
# single data point |
445 | 457 |
cell.chart_type = 'bar' |
446 | 458 |
cell.statistic = Statistic.objects.get(slug='fourth') |
... | ... | |
533 | 545 |
assert chart.x_labels == ['2020-10', '2020-11', '2020-12'] |
534 | 546 |
assert chart.raw_series == [([None, 16, 2], {'title': 'Serie 1'}), ([2, 1, None], {'title': 'Serie 2'})] |
535 | 547 | |
548 |
# stacked bar with percent |
|
549 |
cell.chart_type = 'stacked-bar-percent' |
|
550 |
cell.save() |
|
551 | ||
552 |
chart = cell.get_chart() |
|
553 |
assert chart.x_labels == ['2020-10', '2020-11', '2020-12'] |
|
554 |
assert chart.raw_series == [ |
|
555 |
([None, 94.1, 100], {'title': 'Serie 1'}), |
|
556 |
([100, 5.9, None], {'title': 'Serie 2'}), |
|
557 |
] |
|
558 |
assert all(x + y == 100 for x, y in zip(chart.raw_series[0][0], chart.raw_series[1][0]) if x and y) |
|
559 | ||
536 | 560 |
cell.statistic = Statistic.objects.get(slug='no-data') |
537 | 561 |
cell.save() |
538 | 562 | |
539 |
- |