mirror of https://github.com/apache/superset.git
New Charts
This commit is contained in:
parent
056be737af
commit
9ce4f68473
5
TODO.md
5
TODO.md
|
@ -1,5 +1,8 @@
|
|||
# TODO
|
||||
* in/notin filters autocomplete
|
||||
* Highstock, sort legend based on y value: ![stackoverflow](http://stackoverflow.com/questions/6867607/want-to-sort-highcharts-tooltip-results)
|
||||
* compare time ranges
|
||||
* Label
|
||||
* Add verbose_name and label method to metrics and columns
|
||||
* CSV
|
||||
* Save / bookmark / url shortener
|
||||
* on save, process metadata / generate metrics
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
import pandas
|
||||
import copy
|
||||
from pandas.io.json import dumps
|
||||
|
||||
|
||||
class Highchart(object):
|
||||
def __init__(
|
||||
self, df,
|
||||
chart_type="spline",
|
||||
target_div="#chart",
|
||||
polar=False,
|
||||
width=None,
|
||||
height=None,
|
||||
show_legend=True,
|
||||
stockchart=True,
|
||||
title=None,
|
||||
tooltip=None,
|
||||
sort_columns=False,
|
||||
secondary_y=None,
|
||||
mark_right=False,
|
||||
compare=False,
|
||||
stacked=False,
|
||||
logx=False,
|
||||
logy=False,
|
||||
xlim=None,
|
||||
ylim=None,
|
||||
grid=False,
|
||||
zoom=None):
|
||||
self.df = df
|
||||
self.chart_type = chart_type
|
||||
self.chart = chart = {}
|
||||
self.stockchart = stockchart
|
||||
self.sort_columns = sort_columns
|
||||
self.secondary_y = secondary_y or []
|
||||
self.mark_right = mark_right
|
||||
self.compare = compare
|
||||
self.logx = logx
|
||||
self.logy = logy
|
||||
self.xlim = xlim
|
||||
self.ylim = ylim
|
||||
self.zoom = zoom
|
||||
self.polar = polar
|
||||
self.grid = grid
|
||||
|
||||
chart['chart'] = {}
|
||||
chart['chart']["type"] = chart_type
|
||||
chart['chart']['renderTo'] = target_div
|
||||
|
||||
if width:
|
||||
chart['chart']["width"] = width
|
||||
if height:
|
||||
chart['chart']["height"] = height
|
||||
|
||||
chart['chart']['polar'] = polar
|
||||
|
||||
chart["legend"] = {
|
||||
"enabled": show_legend
|
||||
}
|
||||
if title:
|
||||
chart["title"] = {"text": title}
|
||||
if tooltip:
|
||||
chart['tooltip'] = tooltip
|
||||
if self.zoom:
|
||||
chart["zoomType"] = self.zoom
|
||||
|
||||
self.serialize_series()
|
||||
self.serialize_xaxis()
|
||||
self.serialize_yaxis()
|
||||
|
||||
self.chart = chart
|
||||
|
||||
def serialize_series(self):
|
||||
df = self.df
|
||||
chart = self.chart
|
||||
if self.sort_columns:
|
||||
df = df.sort_index()
|
||||
series = df.to_dict('series')
|
||||
chart["series"] = []
|
||||
for name, data in series.items():
|
||||
if df[name].dtype.kind not in "biufc":
|
||||
continue
|
||||
sec = name in self.secondary_y
|
||||
d = {
|
||||
"name": name if not sec or self.mark_right else name + " (right)",
|
||||
"yAxis": int(sec),
|
||||
"data": zip(df.index, data.tolist())
|
||||
}
|
||||
if self.polar:
|
||||
d['data'] = [v for k, v in d['data']]
|
||||
if self.compare:
|
||||
d['compare'] = self.compare # either `value` or `percent`
|
||||
if self.chart_type in ("area", "bar") and self.stacked:
|
||||
d["stacking"] = 'normal'
|
||||
#if kwargs.get("style"):
|
||||
# d["dashStyle"] = pd2hc_linestyle(kwargs["style"].get(name, "-"))
|
||||
chart["series"].append(d)
|
||||
|
||||
def serialize_xaxis(self):
|
||||
df = self.df
|
||||
x_axis = {}
|
||||
if df.index.name:
|
||||
x_axis["title"] = {"text": df.index.name}
|
||||
if df.index.dtype.kind in "M":
|
||||
x_axis["type"] = "datetime"
|
||||
if df.index.dtype.kind == 'O':
|
||||
chart['xAxis']['categories'] = sorted(list(df.index)) if self.sort_columns else list(df.index)
|
||||
if self.grid:
|
||||
x_axis["gridLineWidth"] = 1
|
||||
x_axis["gridLineDashStyle"] = "Dot"
|
||||
if self.logx:
|
||||
x_axis["type"] = 'logarithmic'
|
||||
if self.xlim:
|
||||
x_axis["min"] = self.xlim[0]
|
||||
x_axis["max"] = self.xlim[1]
|
||||
'''
|
||||
if "rot" in kwargs:
|
||||
x_axis["labels"] = {"rotation": kwargs["rot"]}
|
||||
if "fontsize" in kwargs:
|
||||
x_axis.setdefault("labels", {})["style"] = {"fontSize": kwargs["fontsize"]}
|
||||
if "xticks" in kwargs:
|
||||
x_axis["tickPositions"] = kwargs["xticks"]
|
||||
'''
|
||||
self.x_axis = x_axis
|
||||
|
||||
def serialize_yaxis(self):
|
||||
yAxis = {}
|
||||
chart = self.chart
|
||||
if self.grid:
|
||||
yAxis["gridLineWidth"] = 1
|
||||
yAxis["gridLineDashStyle"] = "Dot"
|
||||
if self.logy:
|
||||
yAxis["type"] = 'logarithmic'
|
||||
if self.ylim:
|
||||
yAxis["min"] = self.ylim[0]
|
||||
yAxis["max"] = self.ylim[1]
|
||||
'''
|
||||
if "rot" in kwargs:
|
||||
yAxis["labels"] = {"rotation": kwargs["rot"]}
|
||||
if "fontsize" in kwargs:
|
||||
yAxis.setdefault("labels", {})["style"] = {"fontSize": kwargs["fontsize"]}
|
||||
if "yticks" in kwargs:
|
||||
yAxis["tickPositions"] = kwargs["yticks"]
|
||||
'''
|
||||
chart["yAxis"] = [yAxis]
|
||||
if self.secondary_y:
|
||||
yAxis2 = copy.deepcopy(yAxis)
|
||||
yAxis2["opposite"] = True
|
||||
chart["yAxis"].append(yAxis2)
|
||||
|
||||
|
||||
@property
|
||||
def javascript_cmd(self):
|
||||
js = dumps(self.chart)
|
||||
if self.stockchart:
|
||||
return "new Highcharts.StockChart({});".format(js)
|
||||
return "new Highcharts.Chart({});".format(js)
|
32
app/viz.py
32
app/viz.py
|
@ -1,19 +1,18 @@
|
|||
from pydruid.utils.filters import Dimension, Filter
|
||||
from datetime import datetime
|
||||
from flask import render_template, flash, request
|
||||
from flask import flash, request
|
||||
import pandas as pd
|
||||
from pandas_highcharts.core import serialize
|
||||
from pydruid.utils import aggregators as agg
|
||||
from collections import OrderedDict
|
||||
from app import utils
|
||||
from app.highchart import Highchart
|
||||
from wtforms import Form, SelectMultipleField, SelectField, TextField
|
||||
import config
|
||||
|
||||
|
||||
CHART_ARGS = {
|
||||
'figsize': (None, 700),
|
||||
'height': 700,
|
||||
'title': None,
|
||||
'render_to': 'chart',
|
||||
'target_div': 'chart',
|
||||
}
|
||||
|
||||
class OmgWtForm(Form):
|
||||
|
@ -220,8 +219,8 @@ class HighchartsViz(BaseViz):
|
|||
|
||||
class TimeSeriesViz(HighchartsViz):
|
||||
verbose_name = "Time Series - Line Chart"
|
||||
chart_kind = "spline"
|
||||
chart_type = 'stock'
|
||||
chart_type = "spline"
|
||||
highstock = True
|
||||
|
||||
def render(self):
|
||||
metrics = self.metrics
|
||||
|
@ -237,12 +236,13 @@ class TimeSeriesViz(HighchartsViz):
|
|||
if rolling_type == 'mean':
|
||||
df = pd.rolling_mean(df, int(rolling_periods))
|
||||
|
||||
chart_js = serialize(
|
||||
df, kind=self.chart_kind,
|
||||
viz=self,
|
||||
chart = Highchart(
|
||||
df,
|
||||
compare=self.compare,
|
||||
chart_type=self.chart_type, stacked=self.stacked, **CHART_ARGS)
|
||||
return super(TimeSeriesViz, self).render(chart_js=chart_js)
|
||||
chart_type=self.chart_type,
|
||||
stacked=self.stacked,
|
||||
**CHART_ARGS)
|
||||
return super(TimeSeriesViz, self).render(chart_js=chart.javascript_cmd)
|
||||
|
||||
def form_class(self):
|
||||
return form_factory(self.datasource, request.args,
|
||||
|
@ -297,23 +297,23 @@ class TimeSeriesCompareViz(TimeSeriesViz):
|
|||
class TimeSeriesAreaViz(TimeSeriesViz):
|
||||
verbose_name = "Time Series - Stacked Area Chart"
|
||||
stacked=True
|
||||
chart_kind = "area"
|
||||
chart_type = "area"
|
||||
|
||||
|
||||
class TimeSeriesBarViz(TimeSeriesViz):
|
||||
verbose_name = "Time Series - Bar Chart"
|
||||
chart_kind = "bar"
|
||||
chart_type = "bar"
|
||||
|
||||
|
||||
class TimeSeriesStackedBarViz(TimeSeriesViz):
|
||||
verbose_name = "Time Series - Stacked Bar Chart"
|
||||
chart_kind = "bar"
|
||||
chart_type = "bar"
|
||||
stacked = True
|
||||
|
||||
|
||||
class DistributionBarViz(HighchartsViz):
|
||||
verbose_name = "Distribution - Bar Chart"
|
||||
chart_kind = "bar"
|
||||
chart_type = "bar"
|
||||
|
||||
def query_obj(self):
|
||||
d = super(DistributionBarViz, self).query_obj()
|
||||
|
|
|
@ -2,7 +2,6 @@ flask
|
|||
flask-alembic
|
||||
flask-appbuilder
|
||||
pandas
|
||||
pandas-highcharts
|
||||
parsedatetime
|
||||
pydruid
|
||||
python-dateutil
|
||||
|
|
Loading…
Reference in New Issue