--- name: confidence_interval_mean kind: function lang: py domain: datascience version: "1.0.0" purity: pure signature: "def confidence_interval_mean(data: list, other: list = None, confidence: float = 0.95) -> dict" description: "Intervalo de confianza (IC) de la media de una muestra con la t de Student, o de la DIFERENCIA de medias de dos muestras independientes con el metodo de Welch (sin asumir varianzas iguales). Una muestra: df=n-1, se=sd_muestral/sqrt(n) (sd con ddof=1), tcrit=t.ppf((1+confidence)/2, df), ci=mean+/-tcrit*se. Dos muestras: IC de mean(data)-mean(other) con se=sqrt(se1^2+se2^2) y grados de libertad de Welch-Satterthwaite. Pura y robusta: nunca lanza; ante casos degenerados (muestra vacia, n<2) devuelve nan + clave note, y con varianza cero el IC colapsa al punto (no es error). Usa scipy.stats y numpy." tags: [papers, statistics, confidence-interval, welch, t-test, python] params: - name: data desc: "muestra de observaciones numericas (lista de numeros). Si other es None, el IC es el de la media de data." - name: other desc: "segunda muestra independiente (lista de numeros) o None (default). Si se da, el IC es el de la diferencia de medias mean(data)-mean(other) calculada con Welch (no asume varianzas iguales)." - name: confidence desc: "nivel de confianza en (0, 1); 0.95 = IC del 95% (default). El cuantil critico es t.ppf((1+confidence)/2, df)." output: "dict {mean, ci_low, ci_high, se, df, confidence, n}. mean = media de data (una muestra) o la diferencia mean(data)-mean(other) (dos muestras). En el caso de dos muestras se anaden ademas n1 y n2 (y n = n1+n2). df son los grados de libertad de la t (Welch-Satterthwaite si dos muestras). Casos degenerados (muestra vacia, n<2) anaden la clave note y dejan ci_low/ci_high/se (y a veces df) en nan; con varianza cero y n>=2 el IC colapsa a [mean, mean] con se=0 (con note, sin nan). Nunca None ni excepcion." uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [scipy, numpy] tested: true tests: ["test_one_sample_golden_contra_scipy", "test_one_sample_distinto_nivel_confianza", "test_welch_diferencia_golden_contra_scipy", "test_edge_un_solo_elemento_no_lanza_nan_note", "test_edge_lista_vacia_no_lanza_note", "test_edge_varianza_cero_colapsa_al_punto", "test_edge_welch_muestra_vacia_no_lanza_note", "test_edge_welch_n1_uno_no_lanza_note"] test_file_path: "python/functions/datascience/confidence_interval_mean_test.py" file_path: "python/functions/datascience/confidence_interval_mean.py" --- ## Ejemplo ```python from datascience import confidence_interval_mean # IC del 95% de la media de una muestra (t de Student). data = [2, 4, 4, 4, 5, 5, 7, 9] ci = confidence_interval_mean(data, confidence=0.95) print(ci["mean"]) # -> 5.0 print(ci["df"]) # -> 7.0 (n - 1) print(round(ci["ci_low"], 5), round(ci["ci_high"], 5)) # -> 3.21251 6.78749 (se con sd muestral ddof=1 ~ 2.13809) # IC del 95% de la DIFERENCIA de medias (Welch, no asume varianzas iguales). control = [23.0, 21.0, 25.0, 22.0, 24.0, 26.0] tratado = [18.0, 20.0, 17.0, 19.0, 21.0] diff = confidence_interval_mean(control, tratado, confidence=0.95) print(diff["mean"]) # -> 4.5 (mean(control) - mean(tratado)) print(round(diff["ci_low"], 4), round(diff["ci_high"], 4)) # Si el intervalo no incluye 0, la diferencia es significativa al 5%. # Degenerados: nunca lanza. print(confidence_interval_mean([5])["note"]) # n < 2: ... indefinidos print(confidence_interval_mean([3, 3, 3])["se"]) # -> 0.0 (IC colapsa a [3, 3]) ``` ## Cuando usarla Cuando quieras cuantificar la **incertidumbre de una media estimada** a partir de una muestra: reporta `[ci_low, ci_high]` en vez de un punto suelto para mostrar el rango plausible del valor real al nivel de confianza pedido. Usala tambien para **comparar dos grupos** (A/B test, control vs tratamiento, antes vs despues con grupos independientes): pasa las dos muestras y, si el IC de la diferencia **no incluye el 0**, la diferencia es significativa al nivel `1 - confidence`. Es el complemento del p-valor: ademas de "hay efecto", te dice "de que tamano y con que margen". Para dos muestras usa Welch por defecto, asi que no necesitas comprobar antes si las varianzas son iguales. ## Gotchas - Pura y determinista (no hace I/O, no muta las entradas), pero **no** es stdlib-only: depende de `scipy.stats` y `numpy` (ambos en el venv del proyecto). - Con `other` usa **Welch** (df de Welch-Satterthwaite): NO asume varianzas iguales ni tamanos de muestra iguales. Si necesitas el t-test clasico de varianzas agrupadas (pooled), esta funcion no lo hace. - `sd` se calcula con **ddof=1** (sd muestral), que es lo correcto para el IC de una media con la t. Atajos como `sd_poblacional/sqrt(n)` (ddof=0) dan un intervalo demasiado estrecho. - En el caso de dos muestras, `mean` es la **diferencia** `mean(data) - mean(other)` (no la media de data). El orden importa: el signo del IC depende de cual va primero. - Nunca lanza. Casos degenerados devuelven `nan` en `ci_low`/`ci_high`/`se` (y a veces `df`) mas una clave `note`: muestra vacia o `n < 2` en cualquiera de las muestras. **Excepcion**: con varianza cero y `n >= 2` el IC colapsa al punto `[mean, mean]` con `se = 0` (no es un error, no hay `nan`). - Comprueba `"note" in out` antes de usar `ci_low`/`ci_high` si la muestra puede ser degenerada.