Comparaciones múltiples LSD Fisher

Ronald Aylmer Fisher

1890 - 1962

La primera técnica de comparación por pares fue desarrollada por Fisher en 1935 y se denomina prueba de diferencia menos significativa (LSD). Esta técnica sólo se puede utilizar si el test anova F es significativo.

La idea principal del LSD es calcular la diferencia significativa más pequeña entre dos medias como si estas medias hubieran sido las únicas medias a comparar y declarar significativa cualquier diferencia mayor que el LSD.

Ingrese la cantidad de grupos a comparar

packages = ["https://cdn.holoviz.org/panel/1.3.1/dist/wheels/bokeh-3.3.0-py3-none-any.whl", "https://cdn.holoviz.org/panel/1.3.1/dist/wheels/panel-1.3.1-py3-none-any.whl", "scipy", "matplotlib" ] import js from js import document import panel as pn import pandas as pd import numpy as np import scipy.stats from itertools import combinations from math import sqrt import matplotlib.pyplot as plt from matplotlib.figure import Figure pn.extension() int_input = pn.widgets.IntInput(name='Grupos', value=3, step=1, start=0, end=1000) button_upload = pn.widgets.Button(name='Procesar', button_type='primary', width=100) pn.Column(int_input, button_upload, height=100).servable(target="num_input") button_cal = pn.widgets.Button(name='Calcular', button_type='primary', width=100) row = pn.Row(button_cal) def process_input(*ags, **kws): document.getElementById('boton').innerHTML="" document.getElementById('inf').innerHTML="" document.getElementById('tab8').innerHTML="" document.getElementById('tab9').innerHTML="" document.getElementById('grafico').innerHTML="" document.getElementById('tex_input').innerHTML="Ingrese los Promedios, Desviaciones y tamaños de cada grupo" df_pane = pd.DataFrame() df_anova = pd.DataFrame() anova = pd.DataFrame() df = pd.DataFrame() df2 = pd.DataFrame() graf_pane="" n = 1 while n <= int_input.value: globals()["prom%s" % n]=pn.widgets.FloatInput(name='Promedio grupo %s'% n, value=0., step=1e-1, start=0, end=1000, placeholder='Ingrese promedio ') globals()["dest%s" % n]=pn.widgets.FloatInput(name='Desviación Típica grupo %s'% n, value=0., step=1e-1, start=0, end=1000, placeholder='Ingrese Desviación Típica') globals()["tam%s" % n]=pn.widgets.FloatInput(name='Tamaño grupo %s'% n, value=0., step=1e-1, start=0, end=1000, placeholder='Ingrese Tamaño') pn.Row(globals()["prom%s" % n], globals()["dest%s" % n], globals()["tam%s" % n]).servable(target='tex_input') n +=1 row.servable(target='boton') button_cal.on_click(on_btn_click) def on_btn_click(*ags, **kws): promedios=[] #Se cargan los promedios desvia=[] #Se cargan las desviaciones tama=[] #Se cargan los tamaños producto=0 suma=0 gl = 0 total = 0 n = 1 while n <= int_input.value: promedios.append(globals()["prom%s" % n].value) desvia.append(globals()["dest%s" % n].value) tama.append(globals()["tam%s" % n].value) n +=1 for d,e in zip(desvia,tama): producto += (d**2)*e for d in tama: gl += d for d,e in zip(promedios,tama): suma += d*e promedioT = suma/gl gl_intra = len(promedios)-1 for d,e,f in zip(promedios, desvia, tama): total += ((d-promedioT)**2+(e**2))*f promedio_cuadrados_entre = (total - producto)/gl_intra promedio_cuadrados_dentro = producto/(gl-len(promedios)) valor_F=promedio_cuadrados_entre/promedio_cuadrados_dentro prob = scipy.stats.f.cdf(x=(valor_F), dfn = gl_intra, dfd = gl-len(promedios)) temp = combinations(promedios, 2) #combinaciones de promedios ns = combinations(tama, 2) # combinaciones de los tamaños a=[] #Las agregamos a una lista for i in list(temp): a.append(i) b=[] for i in list(ns): b.append(i) df = pd.DataFrame(a) #Las converimos en data frame df2 = pd.DataFrame(b) df["n1"]=df2[0] #Agregamos los tamaños al df df["n2"]=df2[1] df["dif"]=df[0]-df[1] #le gregamos las diferencias de promedios df["t-value"] = "" #Calculamos las distribución T de las diferencias for i, row in df.iterrows(): df_index2 = df.loc[i] results = abs(df["dif"])/sqrt(((1/df_index2["n1"])+(1/df_index2["n2"]))* promedio_cuadrados_dentro) df["t-value"] = results #Luego agregamos el p-valor df["p-value"]= (1-(scipy.stats.t.cdf(x=df["t-value"] , df=gl-3)))*2 df = df.drop(["n1", "n2"], axis=1) df.loc[df["p-value"] < 0.05,"sig"]="*" df.loc[df["p-value"]>=0.05,"sig"]="" df_pane = pn.pane.DataFrame(df, col_space=80, width=800, justify='left', index=False) anova = pd.DataFrame({ "Origen Variaciones":["Entre grupos", "Dentro de grupos", "Total"], "Suma Cuadrados":[total-producto, producto, total], "GL":[gl_intra, gl-len(promedios), gl-1], "Promedio cuadrados":[promedio_cuadrados_entre, promedio_cuadrados_dentro, ""], "F-value":[valor_F, "", ""], "p-value":[1-prob, "",""] }) df_anova = pn.pane.DataFrame(anova, col_space=100, width=800, justify='left', index=False) pn.Column("## Tabla ANOVA", df_anova, height=150, width=1000).servable(target='tab8') pn.Column("## Tabla de las diferencias", df_pane, "*The mean difference is significant at the 0.05 level.", height=300, width=800).servable(target='tab9') y_error = [] abc = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"] letra = [] indice = 0 while indice < len(promedios): letra.append(abc[indice]) indice +=1 indice = 0 while indice < len(promedios): y_error.append( (desvia[indice]/sqrt(tama[indice]))*1.96) indice +=1 fig = Figure(figsize=(6, 6)) ax = fig.subplots() ax.errorbar(x = letra, y=promedios, yerr=y_error, fmt="--ro", capsize = 10, ecolor = "g", elinewidth=3) ax.set_xlabel('Grupos') ax.set_ylabel('Promedios') ax.set_title('Gráfico de Promedios', fontsize=20) graf_pane= pn.pane.Matplotlib(fig, dpi=70) pn.Row(graf_pane).servable(target="grafico") plt.close('all') button_upload.on_click(process_input)