Escalas lineal, logarítmica y de potencia
Cuándo cada una es la correcta: el crecimiento multiplicativo, el problema del cero en el logaritmo, la raíz cuadrada como única escala honesta para el área, y la escala simétrica.
Elegir el tipo de escala es una decisión sobre qué relación entre los datos quieres que el ojo perciba como constante. Una lineal hace que las diferencias iguales se vean iguales; una logarítmica hace que las razones iguales se vean iguales. Y hay un caso donde no se elige, se obedece: cuando el canal visual es el área, la escala tiene que llevar una raíz cuadrada, y no hacerlo es un error de representación, no una preferencia.
- Elegir entre lineal y logarítmica según la naturaleza del dato.
- Implementar una escala logarítmica y tratar el cero y los negativos.
- Aplicar la escala de raíz cuadrada al codificar por área.
- Usar la escala logarítmica simétrica cuando el dominio cruza el cero.
La lineal y qué presupone
const lineal = (x, [d0, d1], [r0, r1]) =>
r0 + ((x - d0) / (d1 - d0)) * (r1 - r0);
Una escala lineal hace que las diferencias iguales ocupen distancias iguales. La distancia entre 10 y 20 es la misma que entre 1000 y 1010.
Eso es lo correcto cuando la diferencia absoluta es lo que significa algo: temperaturas, saldos, número de unidades vendidas, milisegundos de latencia. Es la escala por omisión y lo será en el noventa por ciento de los casos.
Es lo incorrecto cuando el dato es multiplicativo. Si tu serie tiene valores entre 1 y 1.000.000, una escala lineal aplasta todo lo que esté por debajo de 100.000 contra la línea base: la mitad de tus datos se convierte en una línea plana pegada al eje.
La logarítmica
function escalaLog({ dominio: [d0, d1], rango: [r0, r1], base = 10 }) {
const lb = Math.log(base);
const l0 = Math.log(d0) / lb, l1 = Math.log(d1) / lb;
const escala = (x) => r0 + ((Math.log(x) / lb - l0) / (l1 - l0)) * (r1 - r0);
escala.invert = (y) => Math.pow(base, l0 + ((y - r0) / (r1 - r0)) * (l1 - l0));
return escala;
}
Una logarítmica hace que las razones iguales ocupen distancias iguales. La distancia de 10 a 100 es la misma que de 100 a 1000.
Cuándo es la correcta:
- El dato abarca varios órdenes de magnitud: población de ciudades, tamaño de ficheros, número de seguidores.
- El crecimiento es multiplicativo: interés compuesto, propagación, adopción.
- Lo que importa es el cambio porcentual, no el absoluto.
En una escala logarítmica, una línea recta significa crecimiento exponencial constante. Esa es la propiedad que la hace insustituible en algunos análisis: la pendiente es la tasa de crecimiento, y comparar pendientes es comparar tasas. En una escala lineal, el mismo crecimiento constante produce una curva que se dispara y de la que no se puede leer nada.
El problema del cero. El logaritmo de cero es menos infinito y el de un número negativo no existe. Una escala logarítmica no puede contener el cero en su dominio, y ese es su límite duro. Cualquier dato con valores cero (ventas de un producto que no se vendió ese mes) rompe el gráfico.
Tres tratamientos, en orden de honestidad:
Excluir los ceros y marcarlos. El punto no se dibuja y una anotación indica el hueco. Es lo correcto.
Empezar el dominio en el mínimo distinto de cero. Los ceros se salen por abajo y hay que recortar. Aceptable si los ceros son raros.
Sumar uno a todos los valores. Mal. Cambia los datos y distorsiona la parte baja de la escala de forma no uniforme.
Las marcas de una logarítmica no son las de una lineal. Las marcas mayores van en las potencias de la base (1, 10, 100, 1000) y las menores en los múltiplos dentro de cada década (2, 3, 4… 9, luego 20, 30…). Un eje logarítmico sin marcas menores es difícil de leer, porque el ojo no sabe dónde cae el 50 entre el 10 y el 100.
function marcasLog(d0, d1, base = 10) {
const marcas = [];
const e0 = Math.floor(Math.log(d0) / Math.log(base));
const e1 = Math.ceil(Math.log(d1) / Math.log(base));
for (let e = e0; e <= e1; e++) {
const p = Math.pow(base, e);
for (let m = 1; m < base; m++) {
const v = m * p;
if (v >= d0 && v <= d1) marcas.push({ valor: v, mayor: m === 1 });
}
}
return marcas;
}
La escala de potencia y la raíz cuadrada
function escalaPow({ dominio: [d0, d1], rango: [r0, r1], exponente = 1 }) {
const t = (x) => Math.sign(x) * Math.pow(Math.abs(x), exponente);
const t0 = t(d0), t1 = t(d1);
const escala = (x) => r0 + ((t(x) - t0) / (t1 - t0)) * (r1 - r0);
escala.invert = (y) => {
const v = t0 + ((y - r0) / (r1 - r0)) * (t1 - t0);
return Math.sign(v) * Math.pow(Math.abs(v), 1 / exponente);
};
return escala;
}
Con exponente 0,5 se obtiene la escala de raíz cuadrada, y ese caso concreto tiene una justificación geométrica que no admite discusión.
Cuando codificas una cantidad con el área de un círculo, el área es proporcional al cuadrado del radio. Si haces el radio proporcional al valor, un dato del doble produce un círculo de cuatro veces el área. El ojo, que percibe el área, ve una diferencia de cuatro veces donde el dato dice dos.
// Mal: el radio proporcional al valor
const r = (valor / max) * rMax;
// Bien: el area proporcional al valor
const r = Math.sqrt(valor / max) * rMax;
O con la escala:
const radio = escalaPow({ dominio: [0, max], rango: [0, rMax], exponente: 0.5 });
Esto no es una preferencia estética: es la corrección que hace que la representación se corresponda con el dato. Un gráfico de burbujas con el radio proporcional al valor exagera las diferencias por un factor cuadrático, y es un error frecuente en visualizaciones publicadas.
El nivel 29 añade el matiz experimental: incluso con la raíz cuadrada, la percepción del área subestima las diferencias, porque la magnitud percibida no crece linealmente con el área física. La raíz cuadrada es el mínimo geométricamente correcto, no la corrección perceptual completa.
La logarítmica simétrica
Cuando el dominio cruza el cero (un balance que puede ser positivo o negativo, una variación porcentual) y además abarca varios órdenes de magnitud, ni la lineal ni la logarítmica sirven. La solución es una escala que es lineal cerca del cero y logarítmica lejos:
function escalaSimlog({ dominio: [d0, d1], rango: [r0, r1], constante = 1 }) {
const t = (x) => Math.sign(x) * Math.log1p(Math.abs(x) / constante);
const t0 = t(d0), t1 = t(d1);
const escala = (x) => r0 + ((t(x) - t0) / (t1 - t0)) * (r1 - r0);
escala.invert = (y) => {
const v = t0 + ((y - r0) / (r1 - r0)) * (t1 - t0);
return Math.sign(v) * constante * Math.expm1(Math.abs(v));
};
return escala;
}
La constante marca dónde está la frontera entre el régimen lineal y el logarítmico. Con valor 1, el tramo de menos uno a uno es aproximadamente lineal.
Math.log1p y Math.expm1 no son decoración: calculan log(1+x) y exp(x)-1 con precisión cuando x es pequeño, donde la fórmula directa pierde cifras significativas por cancelación. Es exactamente el caso que esta escala tiene cerca del cero.
Su inconveniente es de comunicación: un eje simlog es difícil de leer para quien no sabe que lo es, porque la relación entre distancia y valor cambia a lo largo del eje. Solo debe usarse con una audiencia técnica y con el eje bien etiquetado.
Existe la tentación de usar una escala logarítmica siempre que los datos abarcan mucho rango, porque «se ve mejor». Se ve más completo y se entiende peor, y hay trabajo experimental que lo documenta.
Los estudios de percepción gráfica sobre ejes logarítmicos encuentran de forma consistente que las audiencias no técnicas leen mal estos gráficos: interpretan la pendiente como si fuera lineal, subestiman las diferencias entre valores grandes, y con frecuencia no reparan en que el eje no es lineal aunque esté etiquetado. Durante la pandemia esto pasó de ser un debate académico a un problema práctico, con estudios que compararon la comprensión de las mismas curvas en escala lineal y logarítmica y encontraron diferencias sustanciales en la capacidad de responder preguntas correctamente.
La conclusión no es que la escala logarítmica sea mala: es que su público es específico. Para un análisis técnico entre gente que sabe leerla, es la herramienta correcta y a veces la única. Para comunicar a una audiencia general, la lineal comunica mejor aunque muestre menos.
Y cuando el rango de los datos hace la lineal inviable, hay dos alternativas antes de recurrir al logaritmo:
Los pequeños múltiplos. Un panel por grupo de magnitud, cada uno con su escala lineal. Se pierde la comparación directa entre paneles y se gana legibilidad dentro de cada uno.
Cambiar la magnitud representada. Si lo que importa es el crecimiento, representa directamente el cambio porcentual con una escala lineal, en lugar de representar el valor absoluto con una logarítmica. El eje pasa a ser algo que la audiencia sabe leer.
La regla que resume: una escala logarítmica es una decisión que hay que justificar y anunciar, no una opción por defecto para datos grandes. Y si la usas, etiqueta el eje explícitamente y no ocultes que las marcas no están equiespaciadas en valor.
Representa la misma serie de crecimiento exponencial con las tres escalas y enséñasela a alguien que no trabaje con datos. Pídele que estime cuántas veces mayor es el último valor que el primero, en cada una de las tres. Anota los tres errores de estimación: será la medida más convincente que tengas de qué escala comunica en tu contexto.