Ir al contenido
wannacode

Gráficos honestos

En resumen: Un gráfico engañoso muestra una tabla verdadera con una impresión falsa (un eje cortado, dos ejes, 3D); uno honesto empieza las barras en cero y enuncia la conclusión en el título.

Problema

«Septiembre se desplomó»

Un compañero envía un gráfico para la reunión con el gerente: los ingresos de los últimos cuatro meses. La barra de septiembre casi ha desaparecido. Parece un desastre.

Pythondatos: las tablas de la tienda

Septiembre es realmente más flojo: 7128,80 € frente a 8812,70 € en agosto. Por qué, lo descubriremos en el proyecto del final del curso. Aquí la pregunta es otra: ¿cuánto más flojo parece en el gráfico, y cuánto más flojo es de verdad?

La idea

Las barras empiezan en cero

El ojo lee una barra por su longitud: una barra el doble de larga significa el doble. Por eso la longitud debe ser el propio número. El gráfico del compañero empieza en 7000 (set_ylim(7000, 10000)), y eso se llama eje truncado. Aquí están los mismos números con un eje desde 7000 y desde 0:

Pythondatos: las tablas de la tienda

La caída real de agosto a septiembre es del 19,1 %. A la izquierda la barra de septiembre es un 92,9 % más corta que la de agosto: la caída parece 4,9 veces mayor. El eje truncado quita los 7000 € de abajo que comparten los dos meses y deja solo la diferencia.

matplotlib empieza las barras en 0 por sí mismo. Un eje truncado viene de set_ylim o de herramientas que «acercan» el eje por su cuenta. Si la diferencia entre las barras no se ve desde 0, es pequeña. Eso también es una respuesta.

Más precisamente, para curiosos

Una línea es distinta: se lee por su pendiente y por cuándo sube y baja, no por la longitud. El eje de una línea puede empezar en otro sitio que no sea 0 si tiene etiqueta. Una línea que cambia unos pocos por ciento parece casi plana en un eje desde 0, y el cambio no se ve.

Pruébalo

Corrige el gráfico

Alguien dibujó los ingresos por mes con un eje desde 7000. Corrige el gráfico: 12 barras con los ingresos de cada mes (monthly, sin los pedidos cancelados), y el eje y empezando en 0 y llegando por encima de diciembre.

Pythondatos: las tablas de la tienda

La idea

Dos ejes y

Los ingresos están en miles de euros, y los pedidos en cientos. Para ponerlos en un gráfico, a menudo se da a la segunda línea su propio eje a la derecha: ax.twinx() crea un nuevo eje y que comparte el eje x con el primero. Pero la escala de cada eje se elige por separado, y cada línea se estira para llenar la suya. Así dos líneas pueden parecer fundidas o separadas, como quiera el autor.

La alternativa honesta es un índice: dividir cada mes entre el primero y multiplicar por 100. by_month / by_month.iloc[0] * 100 lo hace para las dos columnas a la vez (broadcasting sobre las columnas). Entonces las dos líneas están en un eje y empiezan en 100:

Pythondatos: las tablas de la tienda

A la izquierda las líneas casi coinciden, y los ingresos y los pedidos parecen moverse juntos. A la derecha ves la diferencia: en diciembre los ingresos son 171,2 y los pedidos 136,7. Los ingresos crecieron mucho más que los pedidos, porque los pedidos de diciembre también son más grandes. Lo viste también en los diagramas de caja de la lección anterior.

Otra manera honesta son dos gráficos uno debajo del otro, cada uno con su propio eje y etiqueta: plt.subplots(2, 1, sharex=True).

La idea

3D, gráficos circulares e imágenes

Tres cosas que impresionan y engañan:

  • Barras 3D y gráficos circulares 3D. La perspectiva hace mayor lo que está cerca que lo que está lejos. La tercera dimensión no lleva datos; solo distorsiona.
  • Gráficos circulares. El ojo compara ángulos y áreas mucho peor que longitudes. Lo viste en la lección sobre cómo elegir un gráfico: las barras ordenadas dicen lo mismo con más claridad.
  • Un valor en el tamaño de una imagen. Si la imagen crece en altura y en anchura, su área crece con el cuadrado: el doble parece cuatro veces.
1. Los ingresos de un mes son el doble de los de otro. En una presentación se dibujan como una bolsa de dinero, el doble de alta y el doble de ancha que la otra. ¿Cuánto mayor parece?

La idea

Color para la respuesta

El color no es decoración: dice dónde mirar. Un color para lo que importa y gris para el resto es lo más claro. Aquí están los ingresos por mes dos veces: a la izquierda todas las barras son iguales, a la derecha diciembre está coloreado:

Pythondatos: las tablas de la tienda

np.where(monthly.index.month == 12, '#E69F00', 'lightgray') da un color por mes: naranja para diciembre, gris para los demás. color=colors los pone en las barras.

El título de la derecha también funciona: no «Ingresos por mes», sino la conclusión: «Diciembre aporta el 14 % de los ingresos anuales» (exactamente el 14,3 %). El lector lo entiende antes de mirar los ejes.

El naranja #E69F00 es de la paleta Okabe-Ito: ocho colores que las personas que no ven algunos colores pueden distinguir igualmente. Muchas personas no distinguen el rojo del verde. Por eso nunca separes dos cosas solo con rojo y verde. Si necesitas más colores, la paleta tab10 de matplotlib (los colores por defecto, de C0 a C9) también es un buen comienzo.

La idea

Etiquetas en lugar de leyenda

Seis líneas en seis colores y una leyenda en la esquina: el ojo salta entre la línea y la leyenda para averiguar cuál es cuál. Una etiqueta justo junto a la línea se ahorra eso. Aquí están los ingresos por categoría, con una leyenda a la izquierda y con etiquetas a la derecha:

Pythondatos: las tablas de la tienda

ax.text(x, y, 'Cocina') escribe texto en el punto (x, y) de los datos. Los meses son texto, y matplotlib los coloca en las posiciones 0, 1, 2…, así que len(table) - 0.8 queda justo a la derecha del último mes, y 1.3 junto a diciembre. La etiqueta de la cocina tiene el azul de su línea, y la cocina se dibuja la última y más gruesa, así que queda encima.

En diciembre la cocina vende 3240,60 €, 4,4 veces más que su mes medio en el resto del año. Se venden sobre todo sartenes y cuchillos, probablemente como regalos. En el gráfico de la izquierda esto es una de seis líneas, en el de la derecha es lo primero que ves. La tarjeta de regalo no tiene categoría, por eso no está aquí.

Pruébalo

Colores

1. En un gráfico el crecimiento es verde y el descenso es rojo, sin otra diferencia. ¿Cuál es el problema?
2. ¿Por qué en el gráfico de categorías las otras cinco líneas son grises y la cocina azul?

Ejercicio

El gráfico para el informe anual

El gerente quiere un gráfico para el informe anual: los ingresos por mes (monthly), diciembre en color, los demás meses en gris, el eje desde 0 y un título que diga cuánto de los ingresos del año aporta diciembre. Guarda la parte en share y los colores en colors.

Pythondatos: las tablas de la tienda

Test

Ponte a prueba

1. Los ingresos bajan un 19,1 % de agosto a septiembre. En barras con un eje desde 7000, la bajada parece del 92,9 %. ¿Por qué?
2. Una línea muestra el precio medio del café por mes: 13,90 € hasta febrero y 14,90 € desde marzo. ¿Tiene que empezar en 0 el eje y de la línea?
3. ¿Qué tiene de peligroso tener dos ejes y (twinx) en un gráfico?
4. ¿Qué título es mejor para el gráfico de ingresos por mes con diciembre coloreado?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·