Codigo - Design of Experiments: Diseño completamente al azar (DCA)

Modelo con interacciones para diseno factorial.

Scripts para diseno experimental

Diseño Factorial simple completamente al azar en Python

Modelo con interacciones para diseno factorial.

# =============================================================
# DISEÑO 1: FACTORIAL SIMPLE EN ARREGLO COMPLETAMENTE AL AZAR
# Efecto del CaCl2 sobre la firmeza poscosecha del tomate de árbol
# (Solanum betaceum Cav.) — día 20
# =============================================================

import numpy as np
import pandas as pd
from scipy import stats
from scipy.stats import studentized_range
from itertools import combinations
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

# ── 1. DATOS ──────────────────────────────────────────────────
# Firmeza (% del peso inicial) a los 20 días poscosecha
# 15 frutos por tratamiento — 3 tratamientos — N = 45

datos = {
    'Control (0 mM)': [
        32.2352, 29.3778, 32.9146, 36.8536, 28.9463,
        28.9464, 37.1065, 33.4535, 27.8874, 32.4415,
        27.9146, 27.9042, 31.0888, 21.3902, 22.2379
    ],
    '570 mM CaCl2': [
        47.3010, 45.1384, 51.5084, 45.6415, 43.2209,
        57.0351, 48.9163, 50.3241, 43.1612, 47.3870,
        50.5324, 44.4752, 51.8034, 47.1169, 48.5999
    ],
    '862 mM CaCl2': [
        49.2321, 60.5205, 51.9379, 47.1345, 55.7837,
        46.3841, 52.9608, 42.9855, 45.8903, 52.9056,
        55.3969, 52.7883, 51.4680, 50.6149, 45.1988
    ]
}

trts = list(datos.keys())

# ── 2. DATAFRAME LARGO ────────────────────────────────────────
registros = []
for trt, valores in datos.items():
    for i, v in enumerate(valores, 1):
        registros.append({'tratamiento': trt, 'fruto': i, 'firmeza': v})
df = pd.DataFrame(registros)
print('=' * 60)
print('DISEÑO COMPLETAMENTE AL AZAR (DCA) — DATOS')
print('=' * 60)
print(df.to_string(index=False))

# ── 3. ESTADÍSTICAS DESCRIPTIVAS ──────────────────────────────
print('\n' + '=' * 60)
print('ESTADÍSTICAS DESCRIPTIVAS POR TRATAMIENTO')
print('=' * 60)
desc = df.groupby('tratamiento')['firmeza'].agg(
    n='count', media='mean', mediana='median',
    DE=lambda x: x.std(ddof=1),
    minimo='min', maximo='max',
    CV=lambda x: x.std(ddof=1) / x.mean() * 100
).round(4)
print(desc.to_string())

# ── 4. ANOVA ──────────────────────────────────────────────────
grupos     = [np.array(datos[t]) for t in trts]
N          = sum(len(g) for g in grupos)
k          = len(grupos)
grand_mean = np.mean(np.concatenate(grupos))
means      = [g.mean() for g in grupos]
ni         = [len(g) for g in grupos]

SS_trt = sum(n * (m - grand_mean)**2 for n, m in zip(ni, means))
SS_err = sum(np.sum((g - m)**2) for g, m in zip(grupos, means))
SS_tot = SS_trt + SS_err

df_trt = k - 1
df_err = N - k
df_tot = N - 1

MS_trt = SS_trt / df_trt
MS_err = SS_err / df_err
F_val  = MS_trt / MS_err
p_val  = stats.f.sf(F_val, df_trt, df_err)
F_crit = stats.f.ppf(0.95, df_trt, df_err)

print('\n' + '=' * 60)
print('TABLA DE ANÁLISIS DE VARIANZA (ANOVA)')
print('=' * 60)
print(f"{'Fuente':<28} {'SC':>10} {'gl':>4} {'CM':>10} {'F':>8} {'p-valor':>12}")
print('-' * 76)
print(f"{'Tratamientos (CaCl2)':<28} {SS_trt:>10.4f} {df_trt:>4} "
      f"{MS_trt:>10.4f} {F_val:>8.4f} {p_val:>12.6e}")
print(f"{'Error experimental':<28} {SS_err:>10.4f} {df_err:>4} "
      f"{MS_err:>10.4f} {'—':>8} {'—':>12}")
print(f"{'Total':<28} {SS_tot:>10.4f} {df_tot:>4}")
print(f'\nF crítico (α=0.05): {F_crit:.4f}')

# ── 5. COMPARACIONES POR PARES DE TUKEY ───────────────────────
print('\n' + '=' * 60)
print('COMPARACIONES POR PARES DE TUKEY')
print('(p-valor ajustado por distribución del rango estudentizado)')
print('=' * 60)
print(f"{'Comparación':<42} {'Diferencia':>10} {'q obs':>8} {'p-adj':>14}")
print('-' * 78)

for i, j in combinations(range(k), 2):
    diff  = means[i] - means[j]
    se    = np.sqrt(MS_err / ni[i])
    q_obs = abs(diff) / se
    p_adj = float(studentized_range.sf(q_obs, k, df_err))
    comp  = f'{trts[i]}  vs  {trts[j]}'
    print(f"{comp:<42} {diff:>10.4f} {q_obs:>8.4f} {p_adj:>14.4e}")

# ── 6. SUPUESTOS ──────────────────────────────────────────────
residuals = np.concatenate([g - m for g, m in zip(grupos, means)])
sw_stat, sw_p   = stats.shapiro(residuals)
bart_stat, bart_p = stats.bartlett(*grupos)

print('\n' + '=' * 60)
print('VERIFICACIÓN DE SUPUESTOS')
print('=' * 60)
print(f'Shapiro-Wilk (residuales)  W = {sw_stat:.4f},  p = {sw_p:.4f}')
print(f'Bartlett (homocedasticidad) K² = {bart_stat:.4f},  p = {bart_p:.4f}')

# ── 7. GRÁFICAS ───────────────────────────────────────────────
fig, axes = plt.subplots(1, 2, figsize=(11, 4.5))
fig.suptitle('DCA — Firmeza poscosecha del tomate de árbol (día 20)', fontsize=11)

# Boxplot
colores = ['#B5D4F4', '#9FE1CB', '#F5C4B3']
bp = axes[0].boxplot([datos[t] for t in trts], patch_artist=True, widths=0.45,
                     medianprops=dict(color='#2C2C2A', linewidth=2))
for patch, col in zip(bp['boxes'], colores):
    patch.set_facecolor(col); patch.set_edgecolor('#444441')
axes[0].set_xticks([1, 2, 3])
axes[0].set_xticklabels(trts, fontsize=9)
axes[0].set_ylabel('Firmeza (% peso inicial)')
axes[0].set_title('Boxplots por tratamiento')
axes[0].yaxis.grid(True, linestyle='--', alpha=0.4)

# Q-Q residuales
(osm, osr), (slope, intercept, _) = stats.probplot(residuals, dist='norm')
axes[1].scatter(osm, osr, color='#378ADD', s=18, alpha=0.7)
axes[1].plot([osm[0], osm[-1]],
             [slope*osm[0]+intercept, slope*osm[-1]+intercept],
             color='#D85A30', linewidth=1.5)
axes[1].set_xlabel('Cuantiles teóricos')
axes[1].set_ylabel('Residuales ordenados')
axes[1].set_title(f'Q-Q Normal  W={sw_stat:.4f}  p={sw_p:.4f}')
axes[1].yaxis.grid(True, linestyle='--', alpha=0.3)

plt.tight_layout()
plt.savefig('dca_graficas.png', dpi=150, bbox_inches='tight')
plt.show()
print('\nGráfica guardada: dca_graficas.png')
Lenguaje: PythonDescargar script

Notebooks de experimentacion

Análisis estadístico — Diseño completamente al azar (DCA)

EFECTO DEL CLORURO DE CALCIO (CaCl2) SOBRE LA FIRMEZA POSCOSECHA DEL TOMATE DE ÁRBOL (Solanum betaceum Cav.)

Repositorios de DOE

Repositorio factorial

Scripts, datos y reportes de factoriales.

Plantillas de factoriales

Plantillas para disenos 2^k y 3^k.

    Diseño completamente al azar (DCA) - Diseno de Experimentos