Commit fc1e2d0e authored by ismael.rodriguez's avatar ismael.rodriguez

Added binomial test

parent f9118e58
......@@ -65,6 +65,15 @@ def asssistant():
return data
@route('/binomialsign', method=["POST", "OPTIONS"])
@route('/binomialsign/<alpha:float>', method=["POST", "OPTIONS"])
@headers
def binomialsign(alpha=0.05):
values = clean_missing_values(request.json['values'])
statistic, p_value = npt.binomial_sign_test(values.values()[0], values.values()[1])
result = int(p_value<alpha)
return {"result" : result, "statistic" : statistic, "p_value" : p_value}
@route('/wilcoxon', method=["POST", "OPTIONS"])
@route('/wilcoxon/<alpha:float>', method=["POST", "OPTIONS"])
@headers
......
......@@ -52,87 +52,88 @@ G.add_edge("sample_ranking", "aligned_ranks_test", label="k < 5\nor n < 2k")
for edge in G.edges(): G.edge[edge[0]][edge[1]].update({'label': " " + G.edge[edge[0]][edge[1]].get('label', "") + " ", 'style': G.edge[edge[0]][edge[1]].get('style', "")+",filled", 'fillcolor': 'white'})
def evaluate_test(data):
gl = G.copy()
selection = []
# Tree logic
if data['normality'] and data['homocedasticity']:
selection.extend([
G.node["parametric_conditions"],
G.edge["parametric_conditions"]["parametric"],
G.node["parametric"],
G.edge["parametric"]["groups_parametric"],
G.node["groups_parametric"]
gl.node["parametric_conditions"],
gl.edge["parametric_conditions"]["parametric"],
gl.node["parametric"],
gl.edge["parametric"]["groups_parametric"],
gl.node["groups_parametric"]
])
if data['k'] > 2:
selection.extend([
G.edge["groups_parametric"]["anova"],
G.node["anova"]
gl.edge["groups_parametric"]["anova"],
gl.node["anova"]
])
test = 'anova'
else:
selection.extend([
G.edge["groups_parametric"]["paired_ttest"],
G.node["paired_ttest"]
gl.edge["groups_parametric"]["paired_ttest"],
gl.node["paired_ttest"]
])
if data['paired']:
selection.extend([
G.edge["paired_ttest"]["ttest_rel"],
G.node["ttest_rel"]
gl.edge["paired_ttest"]["ttest_rel"],
gl.node["ttest_rel"]
])
test = 'ttest'
else:
selection.extend([
G.edge["paired_ttest"]["ttest_ind"],
G.node["ttest_ind"]
gl.edge["paired_ttest"]["ttest_ind"],
gl.node["ttest_ind"]
])
test = 'ttest_ind'
else:
selection.extend([
G.node["parametric_conditions"],
G.edge["parametric_conditions"]["nonparametric"],
G.node["nonparametric"],
G.edge["nonparametric"]["groups_nonparametric"],
G.node["groups_nonparametric"]
gl.node["parametric_conditions"],
gl.edge["parametric_conditions"]["nonparametric"],
gl.node["nonparametric"],
gl.edge["nonparametric"]["groups_nonparametric"],
gl.node["groups_nonparametric"]
])
if data['k'] > 2:
selection.extend([
G.edge["groups_nonparametric"]["sample_ranking"],
G.node["sample_ranking"]
gl.edge["groups_nonparametric"]["sample_ranking"],
gl.node["sample_ranking"]
])
if data['k'] < 5 or data['n'] < 2*data['k']:
selection.extend([
G.edge["sample_ranking"]["aligned_ranks_test"],
G.node["aligned_ranks_test"]
gl.edge["sample_ranking"]["aligned_ranks_test"],
gl.node["aligned_ranks_test"]
])
test = 'aligned_ranks'
else:
selection.extend([
G.edge["sample_ranking"]["friedman_test"],
G.node["friedman_test"]
gl.edge["sample_ranking"]["friedman_test"],
gl.node["friedman_test"]
])
test = 'friedman'
else:
selection.extend([
G.edge["groups_nonparametric"]["paired_wilcoxon"],
G.node["paired_wilcoxon"]
gl.edge["groups_nonparametric"]["paired_wilcoxon"],
gl.node["paired_wilcoxon"]
])
if data['paired']:
selection.extend([
G.edge["paired_wilcoxon"]["wilcoxon_test"],
G.node["wilcoxon_test"]
gl.edge["paired_wilcoxon"]["wilcoxon_test"],
gl.node["wilcoxon_test"]
])
test = 'wilcoxon'
else:
selection.extend([
G.edge["paired_wilcoxon"]["mannwhitneyu_test"],
G.node["mannwhitneyu_test"]
gl.edge["paired_wilcoxon"]["mannwhitneyu_test"],
gl.node["mannwhitneyu_test"]
])
test = 'mannwhitneyu'
for v in selection: v.update({"fillcolor": fillcolor})
return {'test': test, 'graph': str(nx.to_agraph(G))}
return {'test': test, 'graph': str(nx.to_agraph(gl))}
def clean_missing_values(values, delete_row=True):
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,6 +10,7 @@ from scipy.stats import ttest_ind, ttest_rel, wilcoxon, mannwhitneyu
__all__ = ['anova_test',
'bonferroni_test',
'binomial_sign_test',
'wilcoxon_test',
'test_ranking',
'friedman_test',
......
......@@ -6,6 +6,29 @@ import scipy.stats as st
import itertools as it
def binomial_sign_test(*args):
k = len(args)
if k != 2: raise ValueError('The test needs two samples')
n = len(args[0])
d_plus = 0
d_minus = 0
for i in range(n):
# Zero differences are eliminated
if args[0][i] < args[1][i]:
d_plus = d_plus+1
elif args[0][i] > args[1][i]:
d_minus = d_minus+1
x = max(d_plus, d_minus)
n = d_plus + d_minus
p_value = 2*(1 - st.binom.cdf(x, n, 0.5)) # Two-tailed of the smallest p-value
return x, p_value
def friedman_test(*args):
k = len(args)
if k < 2: raise ValueError('Less than 2 levels')
......
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "POST, GET, OPTIONS , PUT"
AddType image/x-icon .ico
\ No newline at end of file
......@@ -57,7 +57,7 @@ a:hover {
border-color: transparent;
}
.btn-primary:hover, .btn-primary:focus, .btn-primary.active {
.btn-primary:hover, .btn-primary:focus, .btn-primary.active, .btn-primary[disabled]:hover {
background-color: #FF5722;
border-color: transparent;
}
......@@ -214,6 +214,24 @@ a:hover {
border-radius: 3px;
}
/*
* BUTTON MOVING LIKE JAGGER
*/
.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-webkit-animation: spin2 .7s infinite linear;
}
@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}
@keyframes spin {
from { transform: scale(1) rotate(0deg);}
to { transform: scale(1) rotate(360deg);}
}
/*
* Main content
......
......@@ -3,7 +3,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" href="bootstrap-3.1.1/docs/assets/ico/favicon.ico">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<!-- Just for debugging purposes. Don't actually copy this line! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
......
......@@ -152,7 +152,8 @@
</div>
<div id="nonparametric_two_info" class="panel-collapse collapse">
<div class="panel-body">
<p><b>Wilcoxon</b>: Tests the null hypothesis that two related paired samples come from the same distribution. In particular, it tests whether the distribution of the differences between both groups is symmetric about zero. <a href="http://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test" target="_blank">Learn more.</a></p>
<p><b>Wilcoxon</b>: Tests the null hypothesis that two related paired samples come from the same distribution. It assumes that the differences between samples are symmetrical with respect to the median. <a href="http://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test" target="_blank">Learn more.</a></p>
<p><b>Binomial Sign</b>: Tests the null hypothesis that two related paired samples come from the same distribution. It does not assume symmetry but is less powerfull than Wilcoxon. <a href="http://en.wikipedia.org/wiki/Sign_test" target="_blank">Learn more.</a></p>
<p><b>Mann-Whitney-U</b>: Tests the null hypothesis that two non-paired samples come from the same distribution. <a href="http://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test" target="_blank">Learn more.</a></p>
</div>
</div>
......
......@@ -2,6 +2,8 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="http://tec.citius.usc.es/stac/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="http://tec.citius.usc.es/stac/favicon.ico" type="image/x-icon">
<script src="js/loader.js"></script>
<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script>
......@@ -11,7 +13,7 @@
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-59235014-1', 'auto');
ga('create', 'UA-59235014-2', 'auto');
ga('send', 'pageview');
</script>
......@@ -24,7 +26,8 @@
<div id="modals"></div>
<div class="row">
<div class="col-sm-12 col-md-12 main">
<h1 class="page-header"> STAC - Statistical Tests for Algorithm Comparison</h1>
<div align="center"><img src="stac_cover.png" width=50%/></div>
<br/>
<p align="justify">Through this web platform you can verify the results obtained from the learning algorithms applying the statistic tests to the experiments, which, among other uses, support the decision making process (the election of the most suitable algorithm, for example).</p>
......@@ -38,14 +41,14 @@
Reference
</div>
<div class="panel-body">
Ismael Rodríguez-Fdez, Adrián Canosa, Manuel Mucientes, Alberto Bugarín. STAC: a web platform for the comparison of algorithms using statistical tests, 2015. URL http://tec.citius.usc.es/stac
I. Rodríguez-Fdez, A. Canosa, M. Mucientes, A. Bugarín, STAC: a web platform for the comparison of algorithms using statistical tests, in:Proceedings of the 2015 IEEE International Conference on Fuzzy Systems (FUZZ-IEEE), 2015.
</div>
<div class="panel-footer">
<pre class="prettyprint language-bib">
@misc{stac,
@InProceedings{rodriguez-fdez2015stac,
author={Ismael Rodr\'{i}guez-Fdez and Adri\'{a}n Canosa and Manuel Mucientes and Alberto Bugar\'{i}n},
title={{STAC}: a web platform for the comparison of algorithms using statistical tests},
url={http://tec.citius.usc.es/stac},
booktitle = {Proceedings of the 2015 IEEE International Conference on Fuzzy Systems (FUZZ-IEEE)},
year={2015}}</pre>
</div>
</div>
......
......@@ -24,7 +24,7 @@ $(document).ready(function(){
});
if (!sessionStorage.getItem("data")) {
$("#warning").html("There is no file uploaded with the data needed to do the test. Please upload one before applying any test.");
$("#warning").html("There is no file uploaded with the data needed to do the test. Please <a href=\"#modal_fichero\" data-toggle=\"modal\">upload</a> one before applying any test.");
$("#warning").show();
$('#apply').prop('disabled', true);
} else {
......
......@@ -19,24 +19,25 @@ $(document).ready(function() {
header: true,
dynamicTyping: true,
complete: function(results) {
var data = {};
data["dataset"] = [];
var key = results.meta.fields[0];
if (results.data.map(function(row) { return isNaN(row[key]); }).reduce(function(prev, curr, index, array) { return prev && curr; })) {
results.meta.fields = results.meta.fields.splice(1);
results.data.forEach(function(row) {
data["dataset"].push(row[key]);
delete row[key];
try {
if (results.meta.fields.length < 2) throw "Too few columns";
var data = {};
data["dataset"] = [];
var key = results.meta.fields[0];
if (results.data.map(function(row) { return isNaN(row[key]); }).reduce(function(prev, curr, index, array) { return prev && curr; })) {
results.meta.fields = results.meta.fields.splice(1);
results.data.forEach(function(row) {
data["dataset"].push(row[key]);
delete row[key];
});
}
data["names"] = results.meta.fields;
var values = {};
results.meta.fields.forEach(function(field) {
values[field] = [];
});
}
data["names"] = results.meta.fields;
var values = {};
results.meta.fields.forEach(function(field) {
values[field] = [];
});
try {
results.data.forEach(function(row) {
if ($.map(row, function(v) {return v;}).length == results.meta.fields.length) {
results.meta.fields.forEach(function(field) {
......@@ -60,7 +61,7 @@ $(document).ready(function() {
window.location = APP_CONFIG.app_url + "/data.html";
} catch (err) {
$("#danger_file").html("<strong>"+ err +"</strong>");
$("#danger_file").html("<strong>Format not valid, please read the <a href=\"#helpModal\" data-toggle=\"modal\" more-info=\"file\">expected format</a></strong>");
$("#danger_file").show();
$('#formfile').trigger('reset');
}
......@@ -72,6 +73,10 @@ $(document).ready(function() {
if ($(document).find("#file_table").length > 0) {
show_file();
}
$(document).on('hide.bs.modal', '#modal_fichero', function () {
$("#danger_file").hide();
});
});
function show_file() {
......
......@@ -34,6 +34,7 @@ function loadStyle(url, callback) {
loadStyle("fonts/Roboto.css");
loadStyle("css/bootstrap.min.css");
loadStyle("css/dashboard.css");
loadStyle("//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css");
loadScript("js/jquery.min.js", function() {
loadScript("js/config.js", function() {
......
$(document).ready(function(){
function labrozadeangel() {
label = $("#apply label");
label.toggleClass("glyphicon-refresh");
label.toggleClass("glyphicon-refresh-animate");
label.toggleClass("glyphicon-play");
$("#apply").prop("disabled", false);
}
$(document).on('click', '#apply', function() {
if(!sessionStorage.getItem("data")) {
$("#danger").html("<strong>¡Upload a file!</strong> In the top right of the navigation bar you can select and upload a file by clicking <it>Upload file</it>. Then, click <it>Show file</it> to watch its contents.");
......@@ -20,7 +27,11 @@ $(document).ready(function(){
}
}
$("#apply").prop("disabled", true);
label = $("#apply label");
label.toggleClass("glyphicon-play");
label.toggleClass("glyphicon-refresh");
label.toggleClass("glyphicon-refresh-animate");
switch (type) {
case "assistant":
$.ajax({
......@@ -51,7 +62,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "normality":
$.ajax({
......@@ -75,7 +86,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "homocedasticity":
$.ajax({
......@@ -97,7 +108,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "anova":
$.ajax({
......@@ -121,7 +132,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "ttest":
var group1 = $("#group1").val()
......@@ -146,7 +157,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "wilcoxon":
var group1 = $("#group1").val()
......@@ -169,8 +180,30 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
case "binomialsign":
var group1 = $("#group1").val()
var group2 = $("#group2").val()
$.ajax({
type: "POST", url: url, dataType: "json",
contentType: "application/json",
data: JSON.stringify({values: {group1: JSON.parse(sessionStorage.data).values[group1], group2: JSON.parse(sessionStorage.data).values[group2]}}),
success : function(data) {
$("#danger").hide();
$("#warning").hide();
if (data.error) {
$("#danger").html(data.error).show();
} else {
$("#result").html(wilcoxon_table(data, test, alpha)).show();
}
},
error : function(e) {
console.log('error: ' + e);
}
}).always(labrozadeangel);
case "ranking":
$.ajax({
type: "POST", url: url, dataType: "json",
......@@ -194,7 +227,7 @@ $(document).ready(function(){
error : function(e) {
console.log('error: ' + e);
}
});
}).always(labrozadeangel);
break;
}
}
......
......@@ -25,7 +25,11 @@
<p class="bg-warning">The data must be in csv format <label><a href="#helpModal" data-toggle="modal" more-info="file">[?]</a></label></p>
<h5>Insert text:</h5>
<div class="form-group">
<textarea class="form-control" id="import_text" rows="10"></textarea>
<textarea class="form-control" id="import_text" rows="10" placeholder=
"dataset,algorithm1,algorithm2
A,0.1, 0.5
B,0.3,1.2
C, 0.9,0.001"></textarea>
</div>
<h5>Or upload a file:</h5>
<div class="input-group">
......
......@@ -7,11 +7,11 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">STAC Web Platform</a>
<a class="navbar-brand" href="index.html"><img src="stac_logo.png" height="120%"/> Web Platform</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="assistant.html"><span class="glyphicon glyphicon-tree-conifer"></span> Assistant</a></li>
<li><a href="assistant.html"><span class="fa fa-magic"></span> Assistant</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Parametric Tests <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
......
......@@ -26,8 +26,9 @@
<label class="col-lg-5 control-label">Select test<a href="#helpModal" data-toggle="modal" more-info="nonparametric_two"> [?] </a>:</label>
<div class="col-lg-7">
<div class="btn-group-vertical" data-toggle="buttons">
<label name="test_cond" class="btn btn-default active"><input type="radio" name="test" id="option1" value="wilcoxon" checked> Wilcoxon (paired)</label>
<label name="test_cond" class="btn btn-default"><input type="radio" name="test" id="option1" value="mannwhitneyu"> Mann-Whitney-U (unpaired)</label>
<label name="test_cond" class="btn btn-default active"><input type="radio" name="test" id="option1" value="wilcoxon" checked> Wilcoxon</label>
<label name="test_cond" class="btn btn-default"><input type="radio" name="test" id="option1" value="binomialsign"> Binomial Sign</label>
<label name="test_cond" class="btn btn-default"><input type="radio" name="test" id="option1" value="mannwhitneyu"> Mann-Whitney-U</label>
</div>
</div>
</div>
......@@ -70,7 +71,8 @@
<div class="panel-body">
<p><strong>Null hypothesis (H<sub>0</sub>):</strong> The medians of the differences between the two group samples are equal.</p>
<ul type = square>
<li>Wilcoxon: paired data. </li>
<li>Wilcoxon: paired data. Assumes that the differences between samples are symmetrical with respect to the median. </li>
<li>Binomial Sign: paired data. Does not assume symmetry but is less powerfull than Wilcoxon. </li>
<li>Mann-Whitney-U: unpaired data.</li>
</ul>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment