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

Fixing Ranking Services

parent 7497b0ac
......@@ -18,20 +18,21 @@ def headers(func):
def func_wrapper(*args, **kwargs):
response.headers['Access-Control-Allow-Origin'] = '*'
response.content_type = "application/json"
try :
try:
return json.dumps(func(*args, **kwargs))
except Exception, error:
return json.dumps({"error": error})
except Exception as e:
return json.dumps({"error": str(e)})
return func_wrapper
@route('/wilcoxon', method="POST")
@route('/wilcoxon/', method="POST")
@route('/wilcoxon/<alpha:float>', method="POST")
@headers
def wilcoxon(alpha=0.05):
values = clean_missing_values(request.json['values'])
statistic, p_value = st.wilcoxon(values.values()[0], values.values()[1])
result = np.asscalar(p_value<alpha)
result = int(p_value<alpha)
return {"result" : result, "statistic" : statistic, "p_value" : p_value}
......@@ -41,12 +42,12 @@ def wilcoxon(alpha=0.05):
def mannwhitneyu(alpha=0.05):
values = clean_missing_values(request.json['values'], delete_row=False)
statistic, p_value = st.mannwhitneyu(values.values()[0], values.values()[1], use_continuity="false")
result = np.asscalar(p_value*2<alpha)
result = int(p_value*2<alpha)
return {"result" : result, "statistic" : statistic, "p_value" : p_value*2}
def ranking(func):
def func_wrapper(*args, **kwargs):
def func_wrapper(alpha=0.05, *args, **kwargs):
response.headers['Access-Control-Allow-Origin'] = '*'
response.content_type = "application/json"
statistic, p_value, rankings, names, comparisons, z_values, adj_p_values = func(*args, **kwargs)
......@@ -55,12 +56,15 @@ def ranking(func):
"statistic": statistic,
"p_value": p_value,
"rankings": rankings,
"names": names
"names": names,
"result": np.asscalar(p_value < alpha)
},
"post_hoc": {
"comparisons": comparisons,
"statistic": z_values,
"p_value": adj_p_values
"p_value": adj_p_values,
"control": names[0],
"result": [int(adj_p_value < alpha) for adj_p_value in adj_p_values]
}
}
return func_wrapper
......@@ -78,6 +82,35 @@ def friedman(alpha=0.05, post_hoc="bonferroni_dunn_test"):
ranks = {key: ranking_cmp[i] for i,key in enumerate(values.keys())}
comparisons, z_values, _, adj_p_values = getattr(npt, post_hoc)(ranks)
return statistic, p_value, rankings, names, comparisons, z_values, adj_p_values
@route('/friedman-aligned-ranks/', method="POST")
@route('/friedman-aligned-ranks/<alpha:float>', method="POST")
@route('/friedman-aligned-ranks/<post_hoc>', method="POST")
@route('/friedman-aligned-ranks/<post_hoc>/<alpha:float>', method="POST")
@headers
@ranking
def friedman(alpha=0.05, post_hoc="bonferroni_dunn_test"):
values = clean_missing_values(request.json['values'])
statistic, p_value, rankings, ranking_cmp = npt.friedman_aligned_ranks_test(*values.values())
rankings, names = map(list, zip(*sorted(zip(rankings, values.keys()), key=lambda t: t[0])))
ranks = {key: ranking_cmp[i] for i,key in enumerate(values.keys())}
comparisons, z_values, _, adj_p_values = getattr(npt, post_hoc)(ranks)
return statistic, p_value, rankings, names, comparisons, z_values, adj_p_values
@route('/quade/', method="POST")
@route('/quade/<alpha:float>', method="POST")
@route('/quade/<post_hoc>', method="POST")
@route('/quade/<post_hoc>/<alpha:float>', method="POST")
@headers
@ranking
def friedman(alpha=0.05, post_hoc="bonferroni_dunn_test"):
values = clean_missing_values(request.json['values'])
statistic, p_value, rankings, ranking_cmp = npt.quade_test(*values.values())
rankings, names = map(list, zip(*sorted(zip(rankings, values.keys()), key=lambda t: t[0])))
ranks = {key: ranking_cmp[i] for i,key in enumerate(values.keys())}
comparisons, z_values, _, adj_p_values = getattr(npt, post_hoc)(ranks)
return statistic, p_value, rankings, names, comparisons, z_values, adj_p_values
#Servicio para el test de los Rangos Alineados de Friedman.
......
from .tests_parametricos import anova_test, bonferroni_test
from .parametric_tests import *
from .nonparametric_tests import *
__all__ = ['anova_test',
......
# -*- coding: utf-8 -*-
"""
.. Created on Mon Mar 31 17:11:34 2014
.. @author: Adrián
"""
import numpy as np
import scipy as sp
import scipy.stats as st
def anova_test(matriz_datos, alpha=0.05):
#Número de conjuntos de datos.
N = len(matriz_datos)
#Número de algoritmos.
K = len(matriz_datos[0])
#Medias algoritmos.
medias_algoritmos = []
for columna in zip(*matriz_datos):
medias_algoritmos.append(sp.mean(columna))
#Media general.
media_general = sp.mean(medias_algoritmos)
#Variación total (respecto a la media general).
SCT = 0
#Variación dentro del tratamiento o variación del error (cada valor respecto a la
#media de su tratamiento).
SCE = 0
#Variación entre los diferentes tratamientos o algoritmos (efecto de la media de cada
#tratamiento respecto a la media general).
SCTR = 0
for i in range(len(matriz_datos[0])):
x = [conjunto[i] for conjunto in matriz_datos]
......@@ -38,20 +28,16 @@ def anova_test(matriz_datos, alpha=0.05):
SCE = SCE + (elem-medias_algoritmos[i])**2
SCTR = SCTR + (len(x)*(medias_algoritmos[i]-media_general)**2)
#Grados de libertad.
GLT = (N*K)-1
GLTR = K-1
GLE = GLT - GLTR
#Cuadrados medios (suma cuadrados / grados de libertad)
CMT = SCT/GLT
CMTR = SCTR/GLTR
CME = SCE/GLE
#Estadístico (para contrastar diferencia en las medias del factor de columna TR).
F = CMTR/CME
#Cáculo del p_valor.
p_valor = 1 - st.f.cdf(F, GLTR, GLE)
return {"resultado" : np.asscalar(p_valor < alpha), "p_valor" : p_valor, "estadistico" : F,
......@@ -62,81 +48,25 @@ def anova_test(matriz_datos, alpha=0.05):
def bonferroni_test(nombres_algoritmos, medias_algoritmos, cuadrado_medio_error, N, alpha=0.05):
"""Test POST-HOC (comparaciones múltiples) de Anova: Bonferroni.
.. note:: Este tests compara las medias de todos los algoritmos entre sí. Se utiliza
una vez se tenga constancia gracias al análisis de varianzas Anova de que
existen diferencias significativas entre las medias de los algoritmos.
Cada p-valor asociado con la hipótesis H_i se compara con un alpha ajustado
a todas las comparaciones: :math:`p_i < \\frac{\\alpha}{m}`, donde m se
corresponde con el número de comparaciones: :math:`m = \\frac{(K*(K-1))}{2}`.
Args:
nombres_algoritmos: lista de string [K_algoritmos]
Lista que contiene los nombres de los algoritmos involucrados en el contraste.
medias_algoritmos: lista de float [K_algoritmos]
Lista que contiene la media de los resultados obtenidos por cada uno de los
algoritmos en el test de análisis de varianzas (Anova).
cuadrado_medio_error: float
Varianza dentro del tratamiento o algoritmo o del error (se obtiene del test
de análisis de varianzas Anova)
N: int
Número de conjuntos de datos que se corresponden con el número de problemas sobre
los que se aplica el test de análisis de varianzas Anova.
alpha: float, optional (default = 0.05)
Nivel de significancia (probabilidad de error tipo 1) que se quiere utilizar para
contrastar la hipótesis nula del test.
Returns:
dict: diccionario que contiene los siguientes elementos::
resultado: lista de boolean [m_comparaciones]
Lista que contiene los resultados del test de contraste de hipótesis. True indica
que se rechaza la hipótesis nula. False indica que no se rechaza.
p_valores: lista de float [m_comparaciones]
Lista de p-valores ordenada según los valor (de más a menos significancia o de menor
a mayor) calculados para comparar (contrastar las H0 de igualdad de medias) con el
nivel de significancia ajustado.
valores_t: lista de float [m_comparaciones]
Lista ordenada (según p_valores) de estadísticos calculados durante el test. Siguen
una distribución F con (N*K)-K grados de libertad.
comparaciones: lista de string [m_comparaciones]
Lista ordenada (según p_valores) que contiene los nombres de las comparaciones realizadas
en el test port ejemplo: "Alg1 vs Alg2".
alpha: float
Nivel de significancia (probabilidad de error tipo 1) ajustado a las m comparaciones.
p_valores_ajustados: lista de float [m_comparaciones]
p-valores ajustados, los cuales pueden ser comparados con el nivel de significancia
proporcionado sin ajustar
References:
1. Manuel Oviedo - Beatriz Pateiro. *Contraste sobre la igualdad de medias en dos o más poblaciones normales.*
"""
#Número de algoritmos K.
K = len(medias_algoritmos)
#Número posible de comparaciones.
m = (K*(K-1))/2
#Nombres de las comparaciones.
comparaciones = []
for i in range(K-1):
for j in range(i+1,K):
comparaciones.append(nombres_algoritmos[i] + " vs " + nombres_algoritmos[j])
#Cálculo del estadístico T (distribución t de student).
valores_t = []
for i in range(K-1):
for j in range(i+1,K):
valores_t.append((abs(medias_algoritmos[i]-medias_algoritmos[j]))/float(sp.sqrt(cuadrado_medio_error)*sp.sqrt(2/float(N))))
#Cálculo de los p_valores.
p_valores = []
for i in range(m):
p_valores.append(1-st.t.cdf(valores_t[i],(N*K)-K))
#Ordenamiento de las comparaciones, valores_t y p_valores segun el p_valor.
tabla = zip(comparaciones,valores_t,p_valores)
tabla.sort(key=lambda valor: valor[2])
c, z, p = zip(*tabla)
......@@ -144,15 +74,12 @@ def bonferroni_test(nombres_algoritmos, medias_algoritmos, cuadrado_medio_error,
valores_t = list(z)
p_valores = list(p)
#Nuevo alpha.
alpha2 = alpha/float(m)
#Cálculo de los resultados.
resultado = []
for i in range(m):
resultado.append(np.asscalar(p_valores[i]<alpha2))
#Cálculo de los p_valores ajustados.
p_valores_ajustados = []
for i in range(m):
v = m*p_valores[i]
......
......@@ -10,7 +10,7 @@ $(document).ready(function(){
var url = APP_CONFIG.api_url+"/"+test+"/"+alpha;
var post_hoc = $('input[name=post_hoc]:checked').val();
if (post_hoc) var url = APP_CONFIG.api_url+"/"+test+"/"+sessionStorage.getItem("data")+"/"+alpha+"/"+post_hoc;
if (post_hoc) var url = APP_CONFIG.api_url+"/"+test+"/"+post_hoc+"/"+alpha;
switch (type) {
case "normality":
......@@ -142,7 +142,9 @@ $(document).ready(function(){
break;
case "ranking":
$.ajax({
type: "GET", url: url, dataType: "json",
type: "POST", url: url, dataType: "json",
contentType: "application/json",
data: sessionStorage.data,
success : function(data) {
$("#danger").hide();
$("#warning").hide();
......@@ -150,7 +152,7 @@ $(document).ready(function(){
if (data.error) {
$("#danger").html(data.fallo).show();
} else {
var salida = ranking_table(data.test_ranking, test, alpha);
var salida = ranking_table(data.ranking, test, alpha);
if ($("input[name=post_hoc]:checked").attr("comparison") == "control")
salida = salida + control_method_table(data.post_hoc, test, alpha);
else
......@@ -309,13 +311,13 @@ function ranking_table(data, test, alpha) {
salida = salida + "<td>H0 is accepted</td></tr>";
salida = salida + "</tbody></table>";
var salida = salida +
salida = salida +
" <table class=\"table table-hover table-striped\">\
<caption>Ranking</caption>\
<thead><tr><th>Rank</th><th>Algorithm</th></thead>\
<tbody>";
$.each(data.ranking, function(index, value) {
$.each(data.rankings, function(index, value) {
salida = salida + "<tr><td>" + value.toFixed(5) + "</td><td>" + data.names[index] + "</td></tr>";
});
salida = salida + "</tbody></table></div>";
......@@ -326,12 +328,12 @@ function ranking_table(data, test, alpha) {
function control_method_table(data, test, alpha) {
var salida =
"<table class=\"table table-hover table-striped\">\
<caption>Post-hoc (Using "+data.control_method+" as control method)</caption>\
<thead><tr><th>Comparison</th><th>Statistic</th><th>p-value</th><th>Adjusted p-value</th><th>Result</th></tr></thead>\
<caption>Post-hoc (Using "+data.control+" as control method)</caption>\
<thead><tr><th>Comparison</th><th>Statistic</th><th>Adjusted p-value</th><th>Result</th></tr></thead>\
<tbody>";
$.each(data.names, function(index, value) {
salida = salida + "<td>" + data.control_method + " vs " + value + "</td><td>" + data.statistics[index].toFixed(5) + "</td><td>" + data.p_values[index].toFixed(5) + "</td><td>" + data.adjusted_p_values[index].toFixed(5) + "</td>";
$.each(data.comparisons, function(index, value) {
salida = salida + "<td>" + value + "</td><td>" + data.statistic[index].toFixed(5) + "</td><td>" + data.p_value[index].toFixed(5) + "</td>";
if (data.result[index])
salida = salida + "<td>H0 is rejected</td></tr>";
else
......@@ -348,7 +350,7 @@ function multi_posthoc_table(data, test, alpha) {
"<hr><div class=\"table-responsive\">\
<table class=\"table table-hover table-striped\">\
<caption>"+ $("input[value="+test+"]").parent().text() + " test (significance level of " + alpha + ")</caption>\
<thead><tr><th>Comparison</th><th>Statistic</th><th>p-value</th><th>Adjusted p-value</th><th>Result</th></tr></thead>\
<thead><tr><th>Comparison</th><th>Statistic</th><th>Adjusted p-value</th><th>Result</th></tr></thead>\
<tbody>";
if(test == "bonferroni"){
......@@ -361,7 +363,7 @@ function multi_posthoc_table(data, test, alpha) {
});
} else {
$.each(data.comparisons, function(index, value) {
salida = salida + "<tr><td>" + value + "</td><td>" + data.statistics[index].toFixed(5) + "</td><td>" +data.p_values[index].toFixed(5)+ "</td><td>" +data.adjusted_p_values[index].toFixed(5) + "</td>";
salida = salida + "<tr><td>" + value + "</td><td>" + data.statistic[index].toFixed(5) + "</td><td>" +data.p_value[index].toFixed(5)+ "</td>";
if(data.result[index])
salida = salida + "<td>H0 is rejected</td></tr>";
else
......
......@@ -23,8 +23,7 @@
<div class="col-lg-7">
<div class="btn-group-vertical" data-toggle="buttons">
<label name="nombre_test" class="btn btn-default active"><input type="radio" name="test" id="option1" value="friedman" checked>Friedman</label>
<label name="nombre_test" class="btn btn-default"><input type="radio" name="test" id="option2" value="iman-davenport">Iman-Davenport</label>
<label name="nombre_test" class="btn btn-default"><input type="radio" name="test" id="option3" value="rangos-alineados">Friedman Aligned Ranks</label>
<label name="nombre_test" class="btn btn-default"><input type="radio" name="test" id="option3" value="friedman-aligned-ranks">Friedman Aligned Ranks</label>
<label name="nombre_test" class="btn btn-default"><input type="radio" name="test" id="option3" value="quade">Quade</label>
</div>
</div>
......@@ -35,8 +34,8 @@
<div class="btn-group-vertical" data-toggle="buttons">
<label name="nombre_post" class="btn btn-default active"><input type="radio" name="post_hoc" value="bonferroni_dunn_test" comparison="control" checked>Bonferroni-Dunn</label>
<label name="nombre_post" class="btn btn-default"><input type="radio" name="post_hoc" value="holm_test" comparison="control">Holm</label>
<label name="nombre_post" class="btn btn-default"><input type="radio" name="post_hoc" value="finner_test" comparison="control">Finner</label>
<label name="nombre_post" class="btn btn-default"><input type="radio" name="post_hoc" value="hochberg_test" comparison="control">Hochberg</label>
<label name="nombre_post" class="btn btn-default"><input type="radio" name="post_hoc" value="finner_test" comparison="control">Finner</label>
<label name="nombre_post" class="btn btn-default"><input type="radio" name="post_hoc" value="li_test" comparison="control">Li</label>
</div>
</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