Distribuciones de datos
Saber qué tipo de variable tienes es el primer paso. El segundo es entender cómo se distribuyen sus valores: ¿se agrupan en el centro? ¿Hay valores extremos? ¿Es uniforme o sesgada? La distribución es la “forma” de los datos.
Frecuencia absoluta y relativa
La frecuencia absoluta cuenta cuántas veces aparece cada valor. La frecuencia relativa expresa eso como proporción del total.
const notas = [7, 8, 6, 9, 7, 8, 8, 10, 6, 7, 9, 7, 8, 6, 10];
function tablaFrecuencias(arr) {
const total = arr.length;
const conteo = {};
for (const val of arr) {
conteo[val] = (conteo[val] ?? 0) + 1;
}
return Object.entries(conteo)
.sort(([a], [b]) => Number(a) - Number(b))
.map(([valor, fa]) => ({
valor: Number(valor),
fa, // frecuencia absoluta
fr: (fa / total).toFixed(3), // frecuencia relativa
frPct: ((fa / total) * 100).toFixed(1) + '%',
}));
}
console.table(tablaFrecuencias(notas));
Resultado esperado:
valor fa fr frPct
6 3 0.200 20.0%
7 4 0.267 26.7%
8 4 0.267 26.7%
9 2 0.133 13.3%
10 2 0.133 13.3%
Agrupar en intervalos (clases)
Con datos continuos o con muchos valores distintos, agrupar en intervalos es más legible que listar cada valor:
const alturas = [162, 175, 180, 158, 171, 168, 183, 177, 165, 172,
169, 185, 160, 174, 179, 166, 182, 170, 163, 178];
function frecuenciasIntervalos(arr, numClases = 5) {
const min = Math.min(...arr);
const max = Math.max(...arr);
const amplitud = Math.ceil((max - min) / numClases);
const clases = Array.from({ length: numClases }, (_, i) => ({
desde: min + i * amplitud,
hasta: min + (i + 1) * amplitud,
fa: 0,
}));
for (const valor of arr) {
const idx = Math.min(
Math.floor((valor - min) / amplitud),
numClases - 1 // el valor máximo va en la última clase
);
clases[idx].fa++;
}
return clases.map((c) => ({
intervalo: `[${c.desde}, ${c.hasta})`,
fa: c.fa,
fr: (c.fa / arr.length).toFixed(3),
}));
}
console.table(frecuenciasIntervalos(alturas));
Histograma en consola
Sin necesidad de ninguna librería, podemos dibujar un histograma ASCII:
function histogramaConsola(frecuencias) {
const maxFa = Math.max(...frecuencias.map((f) => f.fa));
const escala = 20; // longitud máxima de la barra
for (const { intervalo, fa } of frecuencias) {
const barra = '█'.repeat(Math.round((fa / maxFa) * escala));
console.log(`${intervalo.padEnd(14)} ${barra} (${fa})`);
}
}
histogramaConsola(frecuenciasIntervalos(alturas));
// [158, 163) ████ (2)
// [163, 168) ████████ (4)
// [168, 173) ████████████████████ (6)
// [173, 178) ████████████ (4)
// [178, 186) ████████ (4)
Formas de distribución habituales
| Forma | Qué significa | Ejemplo |
|---|---|---|
| Simétrica | Media ≈ mediana, forma de campana | Alturas de adultos |
| Sesgada a la derecha | Cola larga hacia valores altos (media > mediana) | Salarios, precios de vivienda |
| Sesgada a la izquierda | Cola larga hacia valores bajos | Notas en examen fácil |
| Uniforme | Todos los valores con frecuencia similar | Lanzamiento de un dado |
| Bimodal | Dos picos distintos | Mezcla de dos poblaciones |
// Detectar asimetría básica comparando media y mediana
function detectarSesgo(arr) {
const sorted = [...arr].sort((a, b) => a - b);
const media = arr.reduce((s, x) => s + x, 0) / arr.length;
const n = sorted.length;
const mediana = n % 2 === 0
? (sorted[n / 2 - 1] + sorted[n / 2]) / 2
: sorted[Math.floor(n / 2)];
const diff = media - mediana;
if (Math.abs(diff) < 0.5) return 'Simétrica';
return diff > 0 ? 'Sesgada a la derecha' : 'Sesgada a la izquierda';
}
console.log(detectarSesgo([1, 1, 2, 2, 2, 3, 10, 15])); // Sesgada a la derecha
En la siguiente lección calculamos las medidas de centralización: media, mediana y moda, y entendemos cuándo usar cada una.