diff --git a/panoramix/bin/panoramix b/panoramix/bin/panoramix index 8bb1de17fcf52..a8317241b9c7d 100755 --- a/panoramix/bin/panoramix +++ b/panoramix/bin/panoramix @@ -283,6 +283,20 @@ The source dataset came from [here](https://github.com/hadley/babynames) session.add(slc) slices.append(slc) + slice_name = "Pivot Table" + slc = session.query(Slice).filter_by(slice_name=slice_name).first() + if not slc: + slc = Slice( + slice_name=slice_name, + viz_type='pivot_table', + datasource_type='table', + table=tbl, + params=get_slice_json( + slice_name, viz_type="pivot_table", metrics=['sum__num'], + groupby=['name'], columns=['state'])) + session.add(slc) + slices.append(slc) + print("Creating a dashboard") Dash = models.Dashboard dash = session.query(Dash).filter_by(dashboard_title="Births").first() diff --git a/panoramix/forms.py b/panoramix/forms.py index 4842659a2855a..9048599aa83b8 100644 --- a/panoramix/forms.py +++ b/panoramix/forms.py @@ -91,6 +91,10 @@ def __init__(self, viz): 'Group by', choices=self.choicify(datasource.groupby_column_names), description="One or many fields to group by"), + 'columns': SelectMultipleField( + 'Columns', + choices=self.choicify(datasource.groupby_column_names), + description="One or many fields to pivot as columns"), 'granularity': TextField( 'Time Granularity', default="one day", description=( @@ -182,6 +186,14 @@ def __init__(self, viz): default='linear', description="Line interpolation as defined by d3.js"), 'code': TextAreaField("Code", description="Put your code here", default=''), + 'pandas_aggfunc': SelectField( + "Aggregation function", + choices=self.choicify([ + 'sum', 'mean', 'min', 'max', 'median', 'stdev', 'var']), + default='sum', + description=( + "Aggregate function to apply when pivoting and " + "computing the total rows and columns")), 'size_from': TextField( "Font Size From", default="20", @@ -241,6 +253,7 @@ def get_form(self, previous=False): field_css_classes = {k: ['form-control'] for k in px_form_fields.keys()} select2 = [ 'viz_type', + 'viz_type', 'columns', 'pandas_aggfunc', 'row_limit', 'rolling_type', 'series', 'entity', 'x', 'y', 'size', 'rotation', 'metric', 'limit', 'markup_type',] diff --git a/panoramix/templates/panoramix/viz_pivot_table.html b/panoramix/templates/panoramix/viz_pivot_table.html new file mode 100644 index 0000000000000..032dfca513c6e --- /dev/null +++ b/panoramix/templates/panoramix/viz_pivot_table.html @@ -0,0 +1,41 @@ +{% macro viz_html(viz) %} + {% if viz.request.args.get("async") == "true" %} + {{ viz.get_df().to_html(na_rep='', classes="dataframe table table-striped table-bordered table-condensed")|safe }} + + {% else %} + + + {% endif %} +{% endmacro %} + +{% macro viz_js(viz) %} + {% if viz.form_data.get("async") != "true" %} + + {% endif %} +{% endmacro %} + +{% macro viz_css(viz) %} +{% endmacro %} diff --git a/panoramix/viz.py b/panoramix/viz.py index 709517440fe30..f1cec7d5ed25b 100644 --- a/panoramix/viz.py +++ b/panoramix/viz.py @@ -222,6 +222,52 @@ def get_df(self): return df +class PivotTableViz(BaseViz): + viz_type = "pivot_table" + verbose_name = "Pivot Table" + template = 'panoramix/viz_pivot_table.html' + css_files = ['lib/dataTables/dataTables.bootstrap.css'] + is_timeseries = False + js_files = [ + 'lib/dataTables/jquery.dataTables.min.js', + 'lib/dataTables/dataTables.bootstrap.js'] + form_fields = [ + 'viz_type', + 'granularity', + ('since', 'until'), + 'groupby', + 'columns', + 'metrics', + 'pandas_aggfunc', + ] + + def query_obj(self): + d = super(PivotTableViz, self).query_obj() + if not self.form_data.get('groupby'): + raise Exception("Please choose at least one \"Group by\" field ") + if not self.form_data.get('metrics'): + raise Exception("Please choose at least one metric") + d['groupby'] = list(set(d['groupby']) | set(self.form_data.get('columns'))) + d['is_timeseries'] = False + d['timeseries_limit'] = None + return d + + def get_df(self): + df = super(PivotTableViz, self).get_df() + if ( + self.form_data.get("granularity") == "all" and + 'timestamp' in df): + del df['timestamp'] + df = df.pivot_table( + index=self.form_data.get('groupby'), + columns=self.form_data.get('columns'), + values=self.form_data.get('metrics'), + aggfunc=self.form_data.get('pandas_aggfunc'), + margins=True, + ) + return df + + class MarkupViz(BaseViz): viz_type = "markup" verbose_name = "Markup Widget" @@ -648,6 +694,7 @@ def get_json_data(self): viz_types_list = [ TableViz, + PivotTableViz, NVD3TimeSeriesViz, NVD3CompareTimeSeriesViz, NVD3TimeSeriesStackedViz,