From: Tom Rees Date: Thu, 17 Jan 2013 12:30:37 +0000 Subject: Stacked graphs with sane server-side data wrangling working. Percentage mode half-impemented. X-Git-Url: http://maxious.lambdacomplex.org/git/?p=ckanext-ga-report.git&a=commitdiff&h=1e315a4d6b9a9077dce680a0cc432dc4cb38d21e --- Stacked graphs with sane server-side data wrangling working. Percentage mode half-impemented. --- --- a/ckanext/ga_report/controller.py +++ b/ckanext/ga_report/controller.py @@ -192,24 +192,17 @@ filter(GA_Stat.stat_name==k).\ order_by(GA_Stat.period_name) # Run the query on all months to gather graph data - series = {} - x_axis = set() + graph = {} for stat in q: - x_val = _get_unix_epoch(stat.period_name) - series[ stat.key ] = series.get(stat.key,{}) - series[ stat.key ][x_val] = float(stat.value) - x_axis.add(x_val) - # Common x-axis for all series. Exclude this month (incomplete data) - x_axis = sorted(list(x_axis))[:-1] - # Buffer a rickshaw dataset from the series - def create_graph(series_name, series_data): - return { - 'name':series_name, - 'data':[ {'x':x,'y':series_data.get(x,0)} for x in x_axis ] - } - rickshaw = [ create_graph(name,data) for name, data in series.items() ] - rickshaw = sorted(rickshaw,key=lambda x:x['data'][-1]['y']) - setattr(c, v+'_graph', json.dumps(rickshaw)) + graph[ stat.key ] = graph.get(stat.key,{ + 'name':stat.key, + 'data': [] + }) + graph[ stat.key ]['data'].append({ + 'x':_get_unix_epoch(stat.period_name), + 'y':float(stat.value) + }) + setattr(c, v+'_graph', json.dumps( _to_rickshaw(graph.values(),percentageMode=True) )) # Buffer the tabular data if c.month: @@ -409,22 +402,54 @@ 'x':_get_unix_epoch(entry.period_name), 'y':int(entry.pageviews), }) - + c.graph_data = json.dumps( _to_rickshaw(graph_data.values()) ) return render('ga_report/publisher/read.html') -def _to_rickshaw(data): - num_points = [] +def _to_rickshaw(data, percentageMode=False): + if data==[]: + return data + # Create a consistent x-axis + num_points = [ len(package['data']) for package in data ] + ideal_index = num_points.index( max(num_points) ) + x_axis = [ point['x'] for point in data[ideal_index]['data'] ] + for package in data: + xs = [ point['x'] for point in package['data'] ] + assert set(xs).issubset( set(x_axis) ), (xs, x_axis) + # Zero pad any missing values + for x in set(x_axis).difference(set(xs)): + package['data'].append( {'x':x, 'y':0} ) + assert len(package['data'])==len(x_axis), (len(package['data']),len(x_axis),package['data'],x_axis,set(x_axis).difference(set(xs))) + if percentageMode: + # Transform data into percentage stacks + totals = {} + for x in x_axis: + for package in data: + for point in package['data']: + totals[ point['x'] ] = totals.get(point['x'],0) + point['y'] + # Roll insignificant series into a catch-all + THRESHOLD = 0.01 + significant_series = [] + for package in data: + for point in package['data']: + fraction = float(point['y']) / totals[point['x']] + if fraction>THRESHOLD and not (package in significant_series): + significant_series.append(package) + temp = {} + for package in data: + if package in significant_series: continue + for point in package['data']: + temp[point['x']] = temp.get(point['x'],0) + point['y'] + catch_all = { 'name':'Other','data': [ {'x':x,'y':y} for x,y in temp.items() ] } + # Roll insignificant series into one + data = significant_series + data.append(catch_all) + # Sort the points for package in data: package['data'] = sorted( package['data'], key=lambda x:x['x'] ) - num_points.append( len(package['data']) ) - if len(set(num_points))>1: - example = num_points[ num_points.index(max(num_points)) ] - for package in data: - while len(package['data']) -
+
@@ -44,7 +44,7 @@ }); var graph = new Rickshaw.Graph( { element: document.querySelector("#chart_$id"), - renderer: 'line', + renderer: '$mode', series: all_series , height: 328 }); --- a/ckanext/ga_report/templates/ga_report/site/index.html +++ b/ckanext/ga_report/templates/ga_report/site/index.html @@ -94,20 +94,20 @@
- ${rickshaw_graph(c.browser_versions_graph,'browser-versions')} + ${rickshaw_graph(c.browser_versions_graph,'browser-versions',mode='stack')}

Note: Where a browser has a large number of versions, these have been grouped together.

${stat_table(c.browser_versions)}
- ${rickshaw_graph(c.browsers_graph,'browsers')} + ${rickshaw_graph(c.browsers_graph,'browsers',mode='stack')} ${stat_table(c.browsers)}
- ${rickshaw_graph(c.os_graph,'os')} + ${rickshaw_graph(c.os_graph,'os',mode='stack')} ${stat_table(c.os)}
- ${rickshaw_graph(c.os_versions_graph,'os_versions')} + ${rickshaw_graph(c.os_versions_graph,'os_versions',mode='stack')} ${stat_table(c.os_versions)}
@@ -115,16 +115,16 @@ ${social_table(c.social_referrer_totals)}
- ${rickshaw_graph(c.social_networks_graph, 'social_networks')} + ${rickshaw_graph(c.social_networks_graph, 'social_networks',mode='stack')}

Percentage of visits that were referred from these social networks

${stat_table(c.social_networks, 'Visits')}
- ${rickshaw_graph(c.languages_graph,'languages')} + ${rickshaw_graph(c.languages_graph,'languages',mode='stack')} ${stat_table(c.languages)}
- ${rickshaw_graph(c.country_graph,'country')} + ${rickshaw_graph(c.country_graph,'country',mode='stack')} ${stat_table(c.country)}