New Charts

This commit is contained in:
Maxime 2015-07-23 05:20:10 +00:00
parent 056be737af
commit 9ce4f68473
5 changed files with 176 additions and 18 deletions

View File

@ -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

BIN
app.db

Binary file not shown.

156
app/highchart.py Normal file
View File

@ -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)

View File

@ -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()

View File

@ -2,7 +2,6 @@ flask
flask-alembic
flask-appbuilder
pandas
pandas-highcharts
parsedatetime
pydruid
python-dateutil