dataviz: add stacked bar percent chart type (#52845)
This commit is contained in:
parent
15651beb91
commit
434ac12426
|
@ -45,6 +45,7 @@ class Migration(migrations.Migration):
|
|||
('bar', 'Bar'),
|
||||
('horizontal-bar', 'Horizontal Bar'),
|
||||
('stacked-bar', 'Stacked Bar'),
|
||||
('stacked-bar-percent', 'Stacked Bar (%)'),
|
||||
('line', 'Line'),
|
||||
('pie', 'Pie'),
|
||||
('dot', 'Dot'),
|
||||
|
|
|
@ -190,6 +190,7 @@ class ChartNgCell(CellBase):
|
|||
('bar', _('Bar')),
|
||||
('horizontal-bar', _('Horizontal Bar')),
|
||||
('stacked-bar', _('Stacked Bar')),
|
||||
('stacked-bar-percent', _('Stacked Bar (%)')),
|
||||
('line', _('Line')),
|
||||
('pie', _('Pie')),
|
||||
('dot', _('Dot')),
|
||||
|
@ -306,6 +307,7 @@ class ChartNgCell(CellBase):
|
|||
'bar': pygal.Bar,
|
||||
'horizontal-bar': pygal.HorizontalBar,
|
||||
'stacked-bar': pygal.StackedBar,
|
||||
'stacked-bar-percent': pygal.StackedBar,
|
||||
'line': pygal.Line,
|
||||
'pie': pygal.Pie,
|
||||
'dot': pygal.Dot,
|
||||
|
@ -337,6 +339,9 @@ class ChartNgCell(CellBase):
|
|||
if data
|
||||
]
|
||||
|
||||
if self.chart_type == 'stacked-bar-percent':
|
||||
self.make_percent([serie['data'] for serie in data['series']])
|
||||
|
||||
for serie in data['series']:
|
||||
chart.add(serie['label'], serie['data'])
|
||||
|
||||
|
@ -485,12 +490,16 @@ class ChartNgCell(CellBase):
|
|||
|
||||
def add_data_to_chart(self, chart, data, y_labels):
|
||||
if self.chart_type != 'pie':
|
||||
series_data = []
|
||||
for i, serie_label in enumerate(y_labels):
|
||||
if chart.axis_count < 2:
|
||||
values = data
|
||||
else:
|
||||
values = [data[i][j] for j in range(len(chart.x_labels))]
|
||||
series_data.append(values)
|
||||
chart.add(serie_label, values)
|
||||
if self.chart_type == 'stacked-bar-percent':
|
||||
self.make_percent(series_data)
|
||||
else:
|
||||
# pie, create a serie by data, to get different colours
|
||||
values = data
|
||||
|
@ -529,3 +538,14 @@ class ChartNgCell(CellBase):
|
|||
elif measure == 'percent':
|
||||
percent_formatter = lambda x: '{:.1f}%'.format(x)
|
||||
return percent_formatter
|
||||
|
||||
def make_percent(self, series_data):
|
||||
for i, values in enumerate(zip(*series_data)):
|
||||
sum_values = sum([v for v in values if v is not None])
|
||||
if sum_values == 0:
|
||||
continue
|
||||
|
||||
factor = 100 / sum_values
|
||||
for values in series_data:
|
||||
if values[i] is not None:
|
||||
values[i] = round(values[i] * factor, 1)
|
||||
|
|
|
@ -441,6 +441,18 @@ def test_chartng_cell(app, statistics):
|
|||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# stacked bar with percent
|
||||
cell.chart_type = 'stacked-bar-percent'
|
||||
cell.save()
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([64.5, 54, 0, 61.6], {'title': u'foo'}),
|
||||
([35.5, 46, 100, 38.4], {'title': u'bar'}),
|
||||
]
|
||||
assert all(x + y == 100 for x, y in zip(chart.raw_series[0][0], chart.raw_series[1][0]))
|
||||
|
||||
# single data point
|
||||
cell.chart_type = 'bar'
|
||||
cell.statistic = Statistic.objects.get(slug='fourth')
|
||||
|
@ -533,6 +545,18 @@ def test_chartng_cell_new_api(app, new_api_statistics):
|
|||
assert chart.x_labels == ['2020-10', '2020-11', '2020-12']
|
||||
assert chart.raw_series == [([None, 16, 2], {'title': 'Serie 1'}), ([2, 1, None], {'title': 'Serie 2'})]
|
||||
|
||||
# stacked bar with percent
|
||||
cell.chart_type = 'stacked-bar-percent'
|
||||
cell.save()
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['2020-10', '2020-11', '2020-12']
|
||||
assert chart.raw_series == [
|
||||
([None, 94.1, 100], {'title': 'Serie 1'}),
|
||||
([100, 5.9, None], {'title': 'Serie 2'}),
|
||||
]
|
||||
assert all(x + y == 100 for x, y in zip(chart.raw_series[0][0], chart.raw_series[1][0]) if x and y)
|
||||
|
||||
cell.statistic = Statistic.objects.get(slug='no-data')
|
||||
cell.save()
|
||||
|
||||
|
|
Loading…
Reference in New Issue