From 00de7f4dcc3bf0c1311a99e3ad4ac3fec66ffbdd Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 10 Mar 2019 12:14:19 -0400 Subject: [PATCH 1/3] add line_bar visualization to viz.py --- superset/viz.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/superset/viz.py b/superset/viz.py index 786fad11da942..815356a0bf2df 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -2757,6 +2757,80 @@ def get_data(self, df): return self.nest_values(levels) +class LineBarViz(NVD3Viz): + + """A simple line bar chart with dual axis""" + + viz_type = 'line_bar' + verbose_name = _('Time Series - Line Bar Chart') + sort_series = False + is_timeseries = True + + def query_obj(self): + d = super(LineBarViz, self).query_obj() + m1 = self.form_data.get('metric') + m2 = self.form_data.get('metric_2') + d['metrics'] = [m1, m2] + if not m1: + raise Exception(_('Pick a metric for left(bar) axis!')) + if not m2: + raise Exception(_('Pick a metric for right(line) axis!')) + if m1 == m2: + raise Exception(_('Please choose different metrics' + ' on left and right axis')) + return d + + def to_series(self, df, classed=''): + cols = [] + for col in df.columns: + if col == '': + cols.append('N/A') + elif col is None: + cols.append('NULL') + else: + cols.append(col) + df.columns = cols + series = df.to_dict('series') + chart_data = [] + metrics = [ + self.form_data.get('metric'), + self.form_data.get('metric_2'), + ] + for i, m in enumerate(metrics): + ys = series[m] + if df[m].dtype.kind not in 'biufc': + continue + series_title = m + d = { + 'key': series_title, + 'classed': classed, + 'values': [ + {'x': ds, 'y': ys[ds] if ds in ys else None} + for ds in df.index + ], + 'yAxis': i + 1, + 'type': 'bar' if i == 0 else 'line', + } + chart_data.append(d) + return chart_data + + def get_data(self, df): + fd = self.form_data + df = df.fillna(0) + + if self.form_data.get('granularity') == 'all': + raise Exception(_('Pick a time granularity for your time series')) + + metric = self.get_metric_label(fd.get('metric')) + metric_2 = self.get_metric_label(fd.get('metric_2')) + df = df.pivot_table( + index=DTTM_ALIAS, + values=[metric, metric_2]) + + chart_data = self.to_series(df) + return chart_data + + viz_types = { o.viz_type: o for o in globals().values() if ( From 4c29b26855e13c7345ffbcebb50cc4eaee4a5c04 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 10 Mar 2019 13:45:24 -0400 Subject: [PATCH 2/3] add line_bar viz type --- .../src/explore/controlPanels/LineBar.js | 73 +++++++++++++++++++ .../assets/src/explore/controlPanels/index.js | 2 + .../presets/CommonChartPreset.js | 3 +- superset/viz.py | 11 +-- 4 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 superset/assets/src/explore/controlPanels/LineBar.js diff --git a/superset/assets/src/explore/controlPanels/LineBar.js b/superset/assets/src/explore/controlPanels/LineBar.js new file mode 100644 index 0000000000000..b4fccc240593e --- /dev/null +++ b/superset/assets/src/explore/controlPanels/LineBar.js @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { t } from '@superset-ui/translation'; +import { NVD3TimeSeries, annotations } from './sections'; +import { D3_TIME_FORMAT_OPTIONS } from '../controls'; + +export default { + requiresTime: true, + controlPanelSections: [ + { + label: t('Chart Options'), + expanded: true, + controlSetRows: [ + ['color_scheme'], + ['x_axis_format'], + ], + }, + { + label: t('Y Axis 1 (Bar)'), + expanded: true, + controlSetRows: [ + ['metric', 'y_axis_format'], + ], + }, + { + label: t('Y Axis 2 (Line)'), + expanded: true, + controlSetRows: [ + ['metric_2', 'y_axis_2_format'], + ], + }, + annotations, + ], + controlOverrides: { + metric: { + label: t('Left(Bar) Axis Metric'), + description: t('Choose a metric for left(Bar) axis'), + }, + y_axis_format: { + label: t('Left(Bar) Axis Format'), + }, + metric_2: { + label: t('Right(Line) Axis Metric'), + description: t('Choose a metric for right(Line) axis'), + }, + y_axis_2_format: { + label: t('Right(Line) Axis Format'), + }, + x_axis_format: { + choices: D3_TIME_FORMAT_OPTIONS, + default: 'smart_date', + }, + row_limit: { + default: 50000, + }, + }, +}; diff --git a/superset/assets/src/explore/controlPanels/index.js b/superset/assets/src/explore/controlPanels/index.js index e663f54afb83a..ce0bc257337d5 100644 --- a/superset/assets/src/explore/controlPanels/index.js +++ b/superset/assets/src/explore/controlPanels/index.js @@ -45,6 +45,7 @@ import Histogram from './Histogram'; import Horizon from './Horizon'; import Iframe from './Iframe'; import Line from './Line'; +import LineBar from './LineBar'; import LineMulti from './LineMulti'; import Mapbox from './Mapbox'; import Markup from './Markup'; @@ -95,6 +96,7 @@ export const controlPanelConfigs = extraOverrides({ horizon: Horizon, iframe: Iframe, line: Line, + line_bar: LineBar, line_multi: LineMulti, mapbox: Mapbox, markup: Markup, diff --git a/superset/assets/src/visualizations/presets/CommonChartPreset.js b/superset/assets/src/visualizations/presets/CommonChartPreset.js index a74f1ea28e52d..23db805d1e448 100644 --- a/superset/assets/src/visualizations/presets/CommonChartPreset.js +++ b/superset/assets/src/visualizations/presets/CommonChartPreset.js @@ -23,7 +23,7 @@ import { BigNumberChartPlugin, BigNumberTotalChartPlugin } from '@superset-ui/le // Make sure to import '@superset-ui/legacy-preset-chart-nvd3/lib' // Not '@superset-ui/legacy-preset-chart-nvd3', // which will point to '@superset-ui/legacy-preset-chart-nvd3/esm' by default -import { AreaChartPlugin, BarChartPlugin, BoxPlotChartPlugin, BubbleChartPlugin, DistBarChartPlugin, LineChartPlugin, PieChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3/lib'; +import { AreaChartPlugin, BarChartPlugin, BoxPlotChartPlugin, BubbleChartPlugin, DistBarChartPlugin, LineChartPlugin, LineBarChartPlugin, PieChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3/lib'; import HistogramChartPlugin from '@superset-ui/legacy-plugin-chart-histogram'; import PivotTableChartPlugin from '@superset-ui/legacy-plugin-chart-pivot-table'; import TableChartPlugin from '@superset-ui/legacy-plugin-chart-table'; @@ -46,6 +46,7 @@ export default class CommonChartPreset extends Preset { new FilterBoxChartPlugin().configure({ key: 'filter_box' }), new HistogramChartPlugin().configure({ key: 'histogram' }), new LineChartPlugin().configure({ key: 'line' }), + new LineBarChartPlugin().configure({ key: 'line_bar' }), new PieChartPlugin().configure({ key: 'pie' }), new PivotTableChartPlugin().configure({ key: 'pivot_table' }), new TableChartPlugin().configure({ key: 'table' }), diff --git a/superset/viz.py b/superset/viz.py index 815356a0bf2df..586afc3dc7b56 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -2797,10 +2797,11 @@ def to_series(self, df, classed=''): self.form_data.get('metric_2'), ] for i, m in enumerate(metrics): - ys = series[m] - if df[m].dtype.kind not in 'biufc': + + ys = series[m['label']] + if df[m['label']].dtype.kind not in 'biufc': continue - series_title = m + series_title = m['label'] d = { 'key': series_title, 'classed': classed, @@ -2821,8 +2822,8 @@ def get_data(self, df): if self.form_data.get('granularity') == 'all': raise Exception(_('Pick a time granularity for your time series')) - metric = self.get_metric_label(fd.get('metric')) - metric_2 = self.get_metric_label(fd.get('metric_2')) + metric = utils.get_metric_name(fd.get('metric')) + metric_2 = utils.get_metric_name(fd.get('metric_2')) df = df.pivot_table( index=DTTM_ALIAS, values=[metric, metric_2]) From 770bf70c17df27d52aa81c4479818731d009076e Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 3 Apr 2019 13:04:25 -0400 Subject: [PATCH 3/3] fix: remove unused NVD3TimeSeries import in LineBar control panel --- superset/assets/src/explore/controlPanels/LineBar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/assets/src/explore/controlPanels/LineBar.js b/superset/assets/src/explore/controlPanels/LineBar.js index b4fccc240593e..a41579d6ab1b7 100644 --- a/superset/assets/src/explore/controlPanels/LineBar.js +++ b/superset/assets/src/explore/controlPanels/LineBar.js @@ -17,7 +17,7 @@ * under the License. */ import { t } from '@superset-ui/translation'; -import { NVD3TimeSeries, annotations } from './sections'; +import { annotations } from './sections'; import { D3_TIME_FORMAT_OPTIONS } from '../controls'; export default {