Tabla de Contenidos

03 - Plotnine

Plotnine es una biblioteca de Python para crear gráficos estadísticos. Se basa en la idea de la “gramática de gráficos”, que es un enfoque para crear gráficos que se basa en la combinación de elementos básicos.

Plotnine está inspirado en ggplot de R y comparte muchos de sus conceptos y sintaxis. Por ejemplo, Plotnine utiliza la misma estructura básica que ggplot, con un objeto ggplot() que representa la base del gráfico y funciones geom() que agregan elementos al gráfico.

Además, Plotnine utiliza la misma notación para asignar estéticas a los datos, como aes(“x”, “y”).

Plotnine es una biblioteca potente y versátil que permite crear gráficos estadísticos de alta calidad. Es una herramienta ideal para científicos de datos, analistas y cualquier persona que necesite visualizar datos.

Los tres elementos de un gráfico de Plotnine son:

Estos elementos se combinan para crear gráficos estadísticos de alta calidad.

Vamos a utilizar el dataset olimpiadas para nuestros ejemplos. Este dataset contiene información sobre los atletas que han participado en los juegos olímpicos modernos.

Como siempre, importamos las librerías necesarias:

#Librerías generales
import pandas as pd
from pathlib import Path

#Librerías gráficas
import plotnine as pn

#Configuración
pd.set_option('display.max_columns', 100)

Creamos nuestro DataFrame de Pandas:

#Cargar ficheros
data_loc = Path('data')
athletes_file = data_loc / 'athlete_events.csv'

#Creamos el DataFrame
athletes_data = pd.read_csv(athletes_file)

Mostramos información para ver las columnas que tenemos:

athletes_data.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 271116 entries, 0 to 271115
Data columns (total 15 columns):
 #   Column  Non-Null Count   Dtype  
---  ------  --------------   -----  
 0   ID      271116 non-null  int64  
 1   Name    271116 non-null  object 
 2   Sex     271116 non-null  object 
 3   Age     261642 non-null  float64
 4   Height  210945 non-null  float64
 5   Weight  208241 non-null  float64
 6   Team    271116 non-null  object 
 7   NOC     271116 non-null  object 
 8   Games   271116 non-null  object 
 9   Year    271116 non-null  int64  
 10  Season  271116 non-null  object 
 11  City    271116 non-null  object 
 12  Sport   271116 non-null  object 
 13  Event   271116 non-null  object 
 14  Medal   39783 non-null   object 
dtypes: float64(3), int64(2), object(10)
memory usage: 31.0+ MB

Geometrías

Las geometrías son los elementos básicos que componen un gráfico. Definen el tipo de gráfico que se va a crear, como un gráfico de línea, de barras, de dispersión, etc.

Vamos a mostrar una serie de gráficos con las medallas ganadas por los atletas españoles. Primero creamos un DataFrame con los diferentes tipos de medallas agrupadas por año:

#Seleccionamos sólo los datos de los atletas españoles
athletes_data_spain = athletes_data[athletes_data["Team"] == "Spain"]

#Eliminamos los nulos en la columna Medal para quedarnos sólo con los atletas que ganaron alguna medalla
athletes_data_spain = athletes_data_spain[athletes_data_spain['Medal'].notna()]

#Agrupamos por años con el número total de medallas por tipo
athletes_data_spain_medals = athletes_data_spain.groupby('Year')['Medal'].value_counts().reset_index()

#renombramos la columna count a total
athletes_data_spain_medals.rename(columns={'count': 'Total'}, inplace=True)

athletes_data_spain_medals.head(10)

    Year   Medal  Total
0   1900    Gold      2
1   1920  Silver     23
2   1928    Gold      3
3   1932  Bronze      1
4   1948  Silver      3
5   1952  Silver      1
6   1960  Bronze     14
7   1972  Bronze      1
8   1972    Gold      1
9   1976  Silver      6
10  1980  Silver     19
11  1980  Bronze      3
12  1980    Gold      2
13  1984  Silver     14
14  1984  Bronze      3
15  1984    Gold      2
16  1988  Silver      2
17  1988  Bronze      2
18  1988    Gold      1
19  1992    Gold     48
20  1992  Silver     19
21  1992  Bronze      3
22  1996    Gold     23
23  1996  Bronze     22
24  1996  Silver     21
25  2000  Bronze     20
26  2000  Silver     19
27  2000    Gold      3
28  2004  Silver     15
29  2004  Bronze      9
30  2004    Gold      4
31  2008  Silver     45
32  2008  Bronze     16
33  2008    Gold      7
34  2012  Silver     33
35  2012  Bronze     25
36  2012    Gold      5
37  2016  Silver     19
38  2016  Bronze     17
39  2016    Gold      7

Vamos a ver algunas de las geometrías más comunes.

Gráficos de líneas

Los gráficos de línea son utilizados para mostrar la evolución de una variable a lo largo del tiempo o de otra variable.

Por ejemplo, queremos ver la evolución del total de medallas ganadas a lo largo de las diferentes olimpiadas. Primero creamos un DataFrame para agrupar el total de medallas:

#Creamos un dataframe con el número total de medallas por año
athletes_data_spain_total_medals = athletes_data_spain_medals.groupby('Year')['Total'].sum().reset_index()

athletes_data_spain_total_medals.head(10)

   Year  Total
0  1900      2
1  1920     23
2  1928      3
3  1932      1
4  1948      3
5  1952      1
6  1960     14
7  1972      2
8  1976      6
9  1980     24

Ahora creamos el gráfico. Para eso, indicamos la fuente de los datos, los ejes X e Y (mediante pn.aes()) y el tipo de gráfico (en este caso pn.geom_line):

# Creamos el gráfico de líneas
graph = pn.ggplot(
    athletes_data_spain_total_medals,
    pn.aes(x='Year', y='Total'),
) + pn.geom_line()

# Mostramos el gráfico
graph.draw()

Gráfico de barras

Los gráficos de barras se utilizan para mostrar datos categóricos. Pueden utilizarse para representar el número de elementos en cada categoría, la proporción de elementos en cada categoría o el valor medio de cada categoría.

Por ejemplo, vamos a mostrar el número de cada tipo de medallas ganadas a lo largo de las olimpiadas:

# Creamos el gráfico de barras
graph = pn.ggplot(
    athletes_data_spain_medals,
    pn.aes(x='Medal', y='Total'),
) + pn.geom_bar(stat='sum')

# Mostramos el gráfico
graph.draw()

En este caso, le indicamos que queremos la suma total de cada tipo de medalla con la opción stat='sum' cuando creamos el gráfico de barras.

También podríamos crear un gráfico similar al del anterior punto (medallas totales ganadas por año) con la opción stat='identity', para que el gráfico muestre los datos tal y como están en el DataFrame.

# Creamos el gráfico de barras
graph = pn.ggplot(
    athletes_data_spain_total_medals,
    pn.aes(x='Year', y='Total'),
) + pn.geom_bar(stat='identity')

# Mostramos el gráfico
graph.draw()

Para hacer este último gráfico, podríamos haber utilizado geom_col(), sin necesidad de especificar stat='identity':

# Creamos el gráfico de barras
graph = pn.ggplot(
    athletes_data_spain_total_medals,
    pn.aes(x='Year', y='Total'),
) + pn.geom_col()

# Mostramos el gráfico
graph.draw()

Histograma

Un gráfico de histograma es una representación gráfica de la distribución de una variable. Se utiliza para mostrar la frecuencia de los valores que toma una variable.

Un histograma se compone de una serie de barras, cada una de las cuales representa un rango de valores. La altura de cada barra representa la frecuencia de los valores que se encuentran dentro de ese rango.

Por ejemplo, vamos a crear un gráfico para mostrar la distribución de la edad de los españoles que han ganado alguna medalla:

# Creamos el gráfico de histograma
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x='Age'),
        )
        + pn.geom_histogram(bins=20)
)

# Mostramos el gráfico
graph.draw()

la opción bins se utiliza para indicar la separación del eje x de un gráfico de histograma. El número de bins determina el número de barras que se mostrarán en el gráfico.

Gráfico de dispersión

Un gráfico de dispersión es un tipo de gráfico que muestra la relación entre dos variables numéricas. Cada punto en el gráfico representa un valor de una variable en relación con un valor de la otra variable.

Por ejemplo, vamos a mostrar la relación entre el peso y la altura de los atletas españoles:

# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point()
)

# Mostramos el gráfico
graph.draw()

Como vemos, con un simple gráfico podemos apreciar que existe una alta correlación entre ambas variables.

Modificando el aspecto de los gráficos

Los temas en plotnine son una forma de controlar la apariencia de los gráficos. Se pueden utilizar para cambiar el color, el tamaño, la forma y otros aspectos de los gráficos.

Los temas se pueden aplicar a todos los gráficos o a gráficos individuales. Para aplicar un tema a todos los gráficos, se puede utilizar la función theme_set(). Para aplicar un tema a un gráfico individual, se puede utilizar la función theme().

Los temas de plotnine están predefinidos, pero también se pueden crear temas personalizados.

Vamos a ver como podemos modificar nuestros gráficos usando alguno de esos temas.

Cambiar el color de los puntos

En el ejemplo del gráfico de dispersión, los puntos del gráfico son de color negro. Para cambiar el color de los puntos, podemos utilizar la opción color del tema. Por ejemplo, el siguiente código cambiará el color de los puntos a azul:

# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point(color = "blue")
)

# Mostramos el gráfico
graph.draw()

Cambiar el tamaño de los puntos

Para cambiar el tamaño de los puntos, podemos utilizar la opción size del tema. Por ejemplo, el siguiente código cambiará el tamaño de los puntos a 1:

# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point(color = "blue", size = 1)
)

# Mostramos el gráfico
graph.draw()

Agregar un título al gráfico

Podemos agregar un título al gráfico con la opción ggtitle():

# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point(color = "blue", size = 1)
        + pn.ggtitle("Relación entre la altura y el peso de los atletas españoles")
)

# Mostramos el gráfico
graph.draw()

Modificar las etiquetas

También podemos modificar las etiquetas de ambos ejes con xlab() y ylab():

# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point(color = "blue", size = 1)
        + pn.ggtitle("Relación entre la altura y el peso de los atletas españoles")
        + pn.xlab("Peso")
        + pn.ylab("Altura")
)

# Mostramos el gráfico
graph.draw()

Cambiar el estilo de los puntos

Para cambiar el estilo de los puntos, podemos usar la opción shape:

graph.draw()
# Creamos el gráfico de dispersión
graph = (
        pn.ggplot(
            athletes_data_spain,
            pn.aes(x="Weight", y="Height"),
        )
        + pn.geom_point(color="blue", size=1, shape='x')
        + pn.ggtitle("Relación entre la altura y el peso de los atletas españoles")
        + pn.xlab("Peso")
        + pn.ylab("Altura")
)

# Mostramos el gráfico
graph.draw()

Mostrar información de diferente color

Podemos mostrar la información con diferentes colores según una característica usando la opción fill. Por ejemplo, para mostrar las medallas ganadas por los atletas españoles según el tipo:

# Creamos el gráfico de barras
graph = (
        pn.ggplot(
            athletes_data_spain_medals,
            pn.aes(x="Year", y="Total", fill="Medal"),
        )
        + pn.geom_col()
        + pn.ggtitle("Medallas ganadas por los atletas españoles")
        + pn.xlab("Año")
        + pn.ylab("Total")
)

# Mostramos el gráfico
graph.draw()

Ejercicios

Ejercicio 1.a

Crear un gráfico de barras que muestre el número de medallas ganadas por los atletas de un China en cada deporte.

Ejercicio 1.b

Modifica el gráfico anterior para que se diferencien las medallas cambiando el color según el tipo.

Ejercicio 1.c

Haz las modificaciones necesarias para que el gráfico del ejercicio anterior quede parecido a éste:

Ejercicio 2.a

Crear un gráfico de barras apiladas que muestre la distribución de las medallas ganadas por los atletas de Rusia por año y género. Crea los gráficos separados en dos columnas.

Ejercicio 2.b

Modificar el gráfico anterior para mostrar los gráficos en 2 filas separadas.

Ejercicio 2.c

Modificar el gráfico anterior para mostrar las columnas de medallistas hombres y mujeres juntas.

Ejercicio 2.d

Vuelve a crear el gráfico del ejercicio 2.c eliminando los datos anteriores a 1994.

Ejercicio 2.e

Averigua como modificar el gráfico del ejercicio anterior para que se muestre parecido al siguiente:

Ejercicio 3.a

Crea un gráfico de líneas que muestre cómo ha evolucionado la cantidad de participantes en los Juegos Olímpicos a lo largo de los años similar al siguiente:

Ejercicio 3.b

¿Por qué crees que salen esos dientes de sierra en el gráfico anterior? Arregla los datos para que muestren datos con más relevancia estadística:

Ejercicio 4

Elige 5 deportes y mira a ver la evolución de la participación femenina a lo largo de los años con un gráfico: