Gráficos Avanzados con Altair
+Clase 3 - Gráficos Avanzados
+En la tercera y última clase vimos como crear el siguiente gráfico
+Así se ven nuestros datos
++ | year | +country | +cluster | +pop | +life_expect | +fertility | +
---|---|---|---|---|---|---|
0 | +1955 | +Afghanistan | +0 | +8891209 | +30.332 | +7.7000 | +
1 | +1960 | +Afghanistan | +0 | +9829450 | +31.997 | +7.7000 | +
2 | +1965 | +Afghanistan | +0 | +10997885 | +34.020 | +7.7000 | +
3 | +1970 | +Afghanistan | +0 | +12430623 | +36.088 | +7.7000 | +
4 | +1975 | +Afghanistan | +0 | +14132019 | +38.438 | +7.7000 | +
5 | +1980 | +Afghanistan | +0 | +15112149 | +39.854 | +7.8000 | +
6 | +1985 | +Afghanistan | +0 | +13796928 | +40.822 | +7.9000 | +
7 | +1990 | +Afghanistan | +0 | +14669339 | +41.674 | +8.0000 | +
8 | +1995 | +Afghanistan | +0 | +20881480 | +41.763 | +8.0000 | +
9 | +2000 | +Afghanistan | +0 | +23898198 | +42.129 | +7.4792 | +
Mejorando nuestro gráfico
+En la clase terminamos con este código pero podemos mejorarlo un poco mas
+Código
+slider = alt.binding_range(min=1955, max=2005, step=5)
+select_year = alt.selection_single(
+ name="year", fields=["year"], bind=slider, init={"year": 1955}
+)
+
+base = (
+ alt.Chart(data)
+ .encode(
+ color=alt.Color("cluster", type="nominal"),
+ )
+ .add_selection(select_year)
+ .transform_filter(select_year)
+)
+
+points = base.mark_circle().encode(
+ x=alt.X("fertility", title="Fertilidad"),
+ y=alt.Y("life_expect", title="Esperanza de vida"),
+ size="pop",
+)
+
+top = (
+ base.mark_bar(opacity=0.3)
+ .encode(
+ x=alt.X("fertility", title="", scale=alt.Scale(domain=(0, 8))),
+ y=alt.Y("count()", title=""),
+ )
+ .properties(height=60)
+)
+
+right = (
+ base.mark_bar(opacity=0.3)
+ .encode(
+ x=alt.X("count()", title=""),
+ y=alt.Y("life_expect", title=""),
+ )
+ .properties(width=60)
+)
+
+abajo = alt.hconcat(points, right).resolve_scale(y="shared")
+final = alt.vconcat(top, abajo)
+
+final
El gráfico final
+Nuestro gráfico final se ve así
+Nuestros ejes en los tres gráficos se mantienen sincronizados y nos permite más facilmente entender los cambios entre los años en relación los unos con los otros.
+También verás que los histogramas que hemos creado en el primer gráfico no están contando nuestros datos correctamente. Esto es porque aunque hemos utilizado la función count()
para uno de nuestros componentes X o Y, no hemos ‘agrupado’ los otros datos ‘correctamente’. Por ejemplo, en este histograma (que hemos llamado top
):
Para crear histogramas tenemos que agrupar nuestros datos en “cubetas” (o bins en inglés). Esto es tan simple como agregar el parametro bin = True
a nuestro componente alt.X()
En nuestro código final utilizamos el parametro extent
en el componente Bin
para controlar la extensión de nuestro eje. Aunque puedes ver que utilizando el parametro scale = alt.Scale(domain = (0, 9))
en nuestro componente X funciona, es recomendado utilizar bin = alt.Bin(extent = (0, 9))
Para controlar la extensión de nuestro eje Y, ya que no estamos utilizando Bin
ahí, si vamos a utilizar scale = alt.Scale(domain = (0, 30))
.
Lo mismo hacemos con nuestro gráfico a la derecha:
+Código
+ +points
+Así como arreglamos nuestra escala Y en el gráfico de la arriba y la escala X en el de la derecha, agregamos un scale = alt.Scale()
a nuestro eje X en points
.
No necesitamos arreglar el eje Y ya que al final estamos usando .resolve_scale(y = 'shared'
como puedes ver en la línea 39 del código para nuestro gráfico final)
Código
+ +En este paso aprovechamos para eliminar el título de nuestro eje Y ya que lo vamos a explicar en el título del gráfico final. Además, agregamos un título a nuestra leyenda para la variable “pop”.
+Las escalas tienen dos componentes principales domain
y range
. Una escala puedes imaginarla como una función que toma datos y los códifica a una representación visual. El domain
define el mínimo y máximo de los datos que la escala espera recibir, el range
define el mínimo y el máximo de los valores que va a producir.
Por ejemplo, una escala con domain
de cero a 1 y range
de 0 a 100 va a recibir valores como 0.10, 0.25, y 0.89 y retornar 10, 25 y 89.
En la visualización de datos utilizamos escalas para transformar datos “reales” a valores de componentes visuales como el radio de un círculo o el color de una marca gráfica.
+Así como tenemos escalas que transforman datos de 0-1 a 0-100, tenemos escalas que transforman datos de -10°C - 50°C a colores entre ‘azul claro’ y ‘rojo oscuro’, por ejemplo.
+Hasta ahora, hemos utilizado alt.Scale(domain = (0, 9))
para controlar el mínimo y el máximo de los valores que nuestros componentes (X o Y) esperan recibir. También podemos manipular el mínimo y el máximo de los valores que se pueden producir con estas escalas. En este caso vamos a actualizar el range
de la escala que estamos utilizando para nuestro componente alt.Size()
- el tamaño de nuestros circulos
Código
+ +Puede que ahora la escala Y no sea de 0 a 90 en todas sus variaciones año con año. Esto es porque todavía no usamos el .resolve_scale(y = 'shared')
. En el gráfico final las escalas van a estar sincronizadas.
¡Listo!
+Juntando todo esto (y agregando un título) obtenemos nuestro gráfico final.
+Código
+slider = alt.binding_range(min=1955, max=2005, step=5)
+select_year = alt.selection_single(
+ name="year", fields=["year"], bind=slider, init={"year": 1955}
+)
+
+base = (
+ alt.Chart(data)
+ .encode(
+ color=alt.Color("cluster", type="nominal"),
+ )
+ .add_selection(select_year)
+ .transform_filter(select_year)
+)
+
+points = base.mark_circle().encode(
+ x=alt.X("fertility", title="Fertilidad", scale=alt.Scale(domain=(0, 9))),
+ y=alt.Y("life_expect", title=""),
+ size=alt.Size("pop", title="población", scale=alt.Scale(range=(50, 1500))),
+)
+
+top = (
+ base.mark_bar(opacity=0.3)
+ .encode(
+ x=alt.X("fertility", title="", bin=alt.Bin(extent=(0, 9))),
+ y=alt.Y(
+ "count()",
+ title="",
+ scale=alt.Scale(domain=(0, 30)),
+ ),
+ )
+ .properties(height=60)
+)
+
+right = (
+ base.mark_bar(opacity=0.3)
+ .encode(
+ x=alt.X("count()", title="", scale=alt.Scale(domain=(0, 40))),
+ y=alt.Y("life_expect", title="", bin=alt.Bin(extent=(0, 90))),
+ )
+ .properties(width=60)
+)
+
+abajo = alt.hconcat(points, right).resolve_scale(y="shared")
+final = alt.vconcat(top, abajo)
+
+final.properties(title="Esperanza de vida a través de los años")