diff --git a/rowers/forms.py b/rowers/forms.py index 8746e331..e03a4cbe 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -841,7 +841,8 @@ analysischoices = ( ('boxplot','Box Chart'), ('trendflex','Trend Flex'), ('histo','Histogram'), - ('flexall','Cumulative Flex Chart') + ('flexall','Cumulative Flex Chart'), + ('stats','Statistics'), ) diff --git a/rowers/templates/statsdiv.html b/rowers/templates/statsdiv.html new file mode 100644 index 00000000..a4072f22 --- /dev/null +++ b/rowers/templates/statsdiv.html @@ -0,0 +1,76 @@ + +{% if stats %} +

Statistics

+ + + + + + + + + + + + + + + {% for key, value in stats.items() %} + + + + + + + + + + + {% endfor %} + +
MetricMeanMinimum25%Median75%MaximumStandard Deviation
{{ value.verbosename }}{{ value.mean|floatformat }}{{ value.min|floatformat }}{{ value.firstq|floatformat }}{{ value.median|floatformat }}{{ value.thirdq|floatformat }}{{ value.max|floatformat }}{{ value.std|floatformat }}
+ +{% endif %} + +{% if cordict %} +

Correlation matrix

+

This matrix indicates a positive (+) or negative (-) correlation between two parameters. The Spearman correlation coefficient has values between +1 and -1. Positive correlation between two metrics means that if one metric increases, the other value is also likely to increase. Negative is the opposite. The further from zero, the higher the likelyhood. +

+ + + + + {% for key,value in cordict.items() %} + + {% endfor %} + + + + {% for key, thedict in cordict.items() %} + + + {% for key2,value in thedict.items() %} + + {% endfor %} + + {% endfor %} + +
 
{{ key }}
{{ key }} + {% if value > 0.5 %} +
{{ value|floatformat }}
+ {% elif value > 0.1 %} +
{{ value|floatformat }}
+ {% elif value < -0.5 %} +
{{ value|floatformat }}
+ {% elif value < -0.1 %} +
{{ value|floatformat }}
+ {% else %} +   + {% endif %} +
+ +{% endif %} + + + + diff --git a/rowers/templates/user_analysis_select.html b/rowers/templates/user_analysis_select.html index 266648c1..58a80876 100644 --- a/rowers/templates/user_analysis_select.html +++ b/rowers/templates/user_analysis_select.html @@ -121,7 +121,11 @@ xaxis.show(); yaxis1.show(); yaxis2.show(); - } + } + + if (functionfield.val() == 'stats') { + plotfield.hide(); + } // Setup an event listener for when the state of the @@ -198,6 +202,18 @@ binsize.hide(); errorbars.hide(); } + else if (Value=='stats') { + xaxis.hide(); + yaxis1.hide(); + yaxis2.hide(); + x_param.hide(); + y_param.hide(); + groupby.hide(); + plotfield.hide(); + palette.hide(); + binsize.hide(); + errorbars.hide(); + } }); }); diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index 00279f6a..ff1fe142 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -5,6 +5,19 @@ from __future__ import unicode_literals from __future__ import unicode_literals, absolute_import from rowers.views.statements import * +from jinja2 import Template,Environment,FileSystemLoader + +def floatformat(x,prec=2): + return '{x}'.format(x=round(x,prec)) + + +env = Environment(loader = FileSystemLoader(["rowers/templates"])) +env.filters['floatformat'] = floatformat + + +from django.contrib.staticfiles import finders + + # generic Analysis view - defaultoptions = { @@ -458,11 +471,77 @@ def histodata(workouts, options): script = ''.join(scripta) return(script,div) + +def statsdata(workouts, options): + includereststrokes = options['includereststrokes'] + spmmin = options['spmmin'] + spmmax = options['spmmax'] + workmin = options['workmin'] + workmax = options['workmax'] + ids = options['ids'] + userid = options['userid'] + plotfield = options['plotfield'] + function = options['function'] + + workstrokesonly = not includereststrokes + + ids = [w.id for w in workouts] + + datamapping = { + w.id:w.date for w in workouts + } + + fieldlist,fielddict = dataprep.getstatsfields() + # prepare data frame + datadf,extracols = dataprep.read_cols_df_sql(ids,fieldlist) + + datadf = dataprep.clean_df_stats(datadf,workstrokesonly=workstrokesonly) + + # Create stats + stats = {} + fielddict.pop('workoutstate') + fielddict.pop('workoutid') + + for field,verbosename in fielddict.items(): + thedict = { + 'mean':datadf[field].mean(), + 'min': datadf[field].min(), + 'std': datadf[field].std(), + 'max': datadf[field].max(), + 'median': datadf[field].median(), + 'firstq':datadf[field].quantile(q=0.25), + 'thirdq':datadf[field].quantile(q=0.75), + 'verbosename':verbosename, + } + stats[field] = thedict + + # Create a dict with correlation values + cor = datadf.corr(method='spearman') + cor.fillna(value=0,inplace=True) + cordict = {} + for field1,verbosename in fielddict.items(): + thedict = {} + for field2,verbosename in fielddict.items(): + try: + thedict[field2] = cor.loc[field1,field2] + except KeyError: + thedict[field2] = 0 + + cordict[field1] = thedict + + context = { + 'stats':stats, + 'cordict':cordict, + } + + htmly = env.get_template('statsdiv.html') + html_content = htmly.render(context) + + return('',html_content) def boxplotdata(workouts,options): - includereststrokes = options['includereststrokes'] spmmin = options['spmmin'] spmmax = options['spmmax'] @@ -570,6 +649,8 @@ def analysis_view_data(request,userid=0): script, div = histodata(workouts, options) elif function == 'flexall': script,div = flexalldata(workouts,options) + elif function == 'stats': + script,div = statsdata(workouts,options) else: script = '' div = 'Unknown analysis functions'