Introducción a la visualización de datos con Python#

Introducción

  • La visualización de datos es el arte y la ciencia de contar historias cautivadoras con datos.

  • ¿Por qué Python?

  • Python realiza cálculos numéricos y científicos avanzados con librerías como: numpy y scipy, alberga una amplia gama de métodos de de métodos de aprendizaje automático gracias a la disponibilidad del paquete scikit-learn

  • Proporciona una gran interfaz para manipulación de big data gracias a la disponibilidad del paquete pandas y su compatibilidad con Apache Spark

  • Genera gráficos y figuras estéticamente con librerías como seaborn, plotly, etc.

Manejo de datos con pandas DataFrame#

  • La biblioteca pandas es un conjunto de herramientas de código abierto extremadamente ingenioso para manejar manipular y analizar datos estructurados. Las tablas de datos se pueden almacenar en el objeto DataFrame disponible en pandas, y los datos en múltiples formatos (por ejemplo, .csv, .tsv, .xlsx y .json) pueden leerse directamente en un DataFrame.

Lectura de datos desde archivos#

from bokeh.resources import INLINE
import bokeh.io
from bokeh import *
bokeh.io.output_notebook(INLINE)
Loading BokehJS ...
  • Para importar la librería Bokeh, debe instalarla primero con la siguiente orden. La versión especificada permitirá ejecutar las visualizaciones del presente curso, sin ningún conflicto

pip install -U bokeh==2.4.0
  • En este ejercicio, leeremos de un conjunto de datos. En este ejemplo se utiliza el conjunto de datos diamantes

  • Abre un cuaderno jupyter y carga la librería pandas

import pandas as pd
import warnings
warnings.filterwarnings('ignore')
  • Especifique la URL del conjunto de datos:

diamonds_url = "https://raw.githubusercontent.com/lihkir/Uninorte/main/AppliedStatisticMS/DataVisualizationRPython/Lectures/Python/PythonDataSets/diamonds.csv"
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Use the usecols parameter if only specific columns need to be read.

diamonds_df_specific_cols = pd.read_csv(diamonds_url, usecols=['carat','cut','color','clarity'])
diamonds_df_specific_cols.head()
carat cut color clarity
0 0.23 Ideal E SI2
1 0.21 Premium E SI1
2 0.23 Good E VS1
3 0.29 Premium I VS2
4 0.31 Good J SI2

Observación y descripción de datos#

  • En este ejercicio, veremos cómo observar y describir datos en un DataFrame. Volveremos a utilizar el conjunto de datos de diamantes

  • Cargue la librería pandas:

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
  • Observe los datos utilizando la función head:

diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75

Los datos contienen diferentes características de los diamantes, como quilates, calidad de corte, color y precio: carat, cut, color, clarity, depth, table, price como columnas. Ahora, corte, claridad y color son variables categóricas, y x, y, z, profundidad, tabla y precio son variables continuas. Mientras que las variables categóricas toman como valores categorías/nombres únicos, los valores continuos toman números reales como valores.

  • Contar el número de filas y columnas en el DataFrame utilizando la función shape

diamonds_df.shape
(53940, 10)
  • Resumir las columnas utilizando describe() para obtener la distribución de las variables, incluyendo la media, la mediana, el mínimo, el máximo y los diferentes cuartiles

diamonds_df.describe()
carat depth table price x y z
count 53940.000000 53940.000000 53940.000000 53940.000000 53940.000000 53940.000000 53940.000000
mean 0.797940 61.749405 57.457184 3932.799722 5.731157 5.734526 3.538734
std 0.474011 1.432621 2.234491 3989.439738 1.121761 1.142135 0.705699
min 0.200000 43.000000 43.000000 326.000000 0.000000 0.000000 0.000000
25% 0.400000 61.000000 56.000000 950.000000 4.710000 4.720000 2.910000
50% 0.700000 61.800000 57.000000 2401.000000 5.700000 5.710000 3.530000
75% 1.040000 62.500000 59.000000 5324.250000 6.540000 6.540000 4.040000
max 5.010000 79.000000 95.000000 18823.000000 10.740000 58.900000 31.800000
  • Esto funciona para las variables continuas. Sin embargo, para las variables categóricas, necesitamos utilizar el parámetro include=object.

diamonds_df.describe(include=object)
cut color clarity
count 53940 53940 53940
unique 5 7 8
top Ideal G SI1
freq 21551 11292 13065
  • Para obtener información sobre el conjunto de datos, utilice el método info():

diamonds_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 53940 entries, 0 to 53939
Data columns (total 10 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   carat    53940 non-null  float64
 1   cut      53940 non-null  object 
 2   color    53940 non-null  object 
 3   clarity  53940 non-null  object 
 4   depth    53940 non-null  float64
 5   table    53940 non-null  float64
 6   price    53940 non-null  int64  
 7   x        53940 non-null  float64
 8   y        53940 non-null  float64
 9   z        53940 non-null  float64
dtypes: float64(6), int64(1), object(3)
memory usage: 4.1+ MB
  • Podemos acceder a la columna corte del DataFrame diamonds_df con diamonds_df.cut o diamonds_df[‘cut’]

  • Ahora, ¿qué tal si seleccionamos todas las filas correspondientes a los diamantes que tienen la talla Ideal y almacenarlas en un DataFrame separado? Podemos seleccionarlas utilizando la función loc para seleccionarlos:

diamonds_low_df = diamonds_df.loc[diamonds_df['cut']=='Ideal']
diamonds_low_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
11 0.23 Ideal J VS1 62.8 56.0 340 3.93 3.90 2.46
13 0.31 Ideal J SI2 62.2 54.0 344 4.35 4.37 2.71
16 0.30 Ideal I SI2 62.0 54.0 348 4.31 4.34 2.68
39 0.33 Ideal I SI2 61.8 55.0 403 4.49 4.51 2.78

Añadir nuevas columnas al DataFrame#

  • En este ejercicio, vamos a añadir nuevas columnas al conjunto de datos de diamantes en la biblioteca pandas. Empezaremos con la adición simple de columnas y luego avanzaremos y veremos la adición condicional de columnas. Para ello, vamos a seguir los siguientes pasos:

  • Cargue la biblioteca pandas

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Añade una columna price_per_carat al DataFrame. En este ejemplo el precio por quilates. Del mismo modo, también podemos utilizar la suma, la resta y otros operadores matemáticos sobre dos columnas numéricas.

diamonds_df['price_per_carat'] = diamonds_df['price']/diamonds_df['carat']
  • Llame a la función head de DataFrame para comprobar si la nueva columna se ha añadido como como se esperaba:

diamonds_df.head()
carat cut color clarity depth table price x y z price_per_carat
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43 1417.391304
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31 1552.380952
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31 1421.739130
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63 1151.724138
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75 1080.645161
  • Ahora, veremos la adición condicional de columnas. Vamos a intentar añadir una columna basada en el valor de price_per_carat, digamos que todo lo que sea más de 3500 como alto (codificado como 1) y todo lo que sea inferior a 3500 como bajo (codificado como 0).

import numpy as np

diamonds_df['price_per_carat_is_high'] = np.where(diamonds_df['price_per_carat'] > 3500, 1, 0)
diamonds_df.tail()
carat cut color clarity depth table price x y z price_per_carat price_per_carat_is_high
53935 0.72 Ideal D SI1 60.8 57.0 2757 5.75 5.76 3.50 3829.166667 1
53936 0.72 Good D SI1 63.1 55.0 2757 5.69 5.75 3.61 3829.166667 1
53937 0.70 Very Good D SI1 62.8 60.0 2757 5.66 5.68 3.56 3938.571429 1
53938 0.86 Premium H SI2 61.0 58.0 2757 6.15 6.12 3.74 3205.813953 0
53939 0.75 Ideal D SI2 62.2 55.0 2757 5.83 5.87 3.64 3676.000000 1

Aplicación de funciones a las columnas de DataFrame#

  • En este ejercicio, consideraremos un escenario en el que el precio de los diamantes ha aumentado y queremos aplicar un factor de incremento de 1.3 al precio de todos los diamantes en nuestro registro. Podemos conseguirlo aplicando una sencilla función. A continuación, redondearemos el precio de los diamantes hasta su tope. Para ello, vamos a seguir los siguientes pasos

  • Cargue la biblioteca pandas

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Aplique una función simple en las columnas utilizando el siguiente código:

diamonds_df['price'] = diamonds_df['price']*1.3
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 423.8 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 423.8 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 425.1 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 434.2 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 435.5 4.34 4.35 2.75
  • Aplicar la función math.ceil para redondear el precio de los diamantes hasta su tope

import math

diamonds_df['rounded_price'] = diamonds_df['price'].apply(math.ceil)
diamonds_df.head()
carat cut color clarity depth table price x y z rounded_price
0 0.23 Ideal E SI2 61.5 55.0 423.8 3.95 3.98 2.43 424
1 0.21 Premium E SI1 59.8 61.0 423.8 3.89 3.84 2.31 424
2 0.23 Good E VS1 56.9 65.0 425.1 4.05 4.07 2.31 426
3 0.29 Premium I VS2 62.4 58.0 434.2 4.20 4.23 2.63 435
4 0.31 Good J SI2 63.3 58.0 435.5 4.34 4.35 2.75 436
  • Puede haber ocasiones en las que tenga que escribir su propia función para realizar la tarea que desea llevar a cabo.

  • Por ejemplo, digamos que quiere añadir otra columna al DataFrame indicando el precio redondeado de los diamantes al múltiplo de 100 (igual o superior al precio).

  • Utilice la función lambda como sigue para redondear el precio de los diamantes al múltiplo de 100 más cercano

import math

diamonds_df['rounded_price_to_100multiple'] = diamonds_df['price'].apply(lambda x: 100*math.ceil(x/100))
diamonds_df.head()
carat cut color clarity depth table price x y z rounded_price rounded_price_to_100multiple
0 0.23 Ideal E SI2 61.5 55.0 423.8 3.95 3.98 2.43 424 500
1 0.21 Premium E SI1 59.8 61.0 423.8 3.89 3.84 2.31 424 500
2 0.23 Good E VS1 56.9 65.0 425.1 4.05 4.07 2.31 426 500
3 0.29 Premium I VS2 62.4 58.0 434.2 4.20 4.23 2.63 435 500
4 0.31 Good J SI2 63.3 58.0 435.5 4.34 4.35 2.75 436 500
  • Por supuesto, no todas las funciones pueden ser escritas en una sola línea y es importante saber cómo incluir funciones definidas por el usuario en la función apply. Vamos a escribir el mismo código con una función definida por el usuario para ilustrarlo.

import math

def get_100_multiple_ceil(x):
    y = 100*math.ceil(x/100)
    return y
 
diamonds_df['rounded_price_to_100multiple']=diamonds_df['price'].apply(get_100_multiple_ceil)
diamonds_df.head()
carat cut color clarity depth table price x y z rounded_price rounded_price_to_100multiple
0 0.23 Ideal E SI2 61.5 55.0 423.8 3.95 3.98 2.43 424 500
1 0.21 Premium E SI1 59.8 61.0 423.8 3.89 3.84 2.31 424 500
2 0.23 Good E VS1 56.9 65.0 425.1 4.05 4.07 2.31 426 500
3 0.29 Premium I VS2 62.4 58.0 434.2 4.20 4.23 2.63 435 500
4 0.31 Good J SI2 63.3 58.0 435.5 4.34 4.35 2.75 436 500

Aplicación de funciones en varias columnas#

  • Supongamos que estamos interesados en comprar diamantes que tengan Ideal cut y color D (totalmente incoloro). Este ejercicio consiste en añadir una nueva columna, desired, al DataFrame, cuyo valor será yes si se cumplen nuestros criterios y no si no se cumplen. Veamos cómo lo hacemos:

  • Cargue la biblioteca pandas

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df_exercise = pd.read_csv(diamonds_url)
diamonds_df_exercise.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Write a function to determine whether a record, x, is desired or not:

def is_desired(x):
    bool_var = 'yes' if (x['cut']=='Ideal' and x['color']=='D') else 'no'
    return bool_var
  • Utilice la función apply para añadir la nueva columna, desired:

diamonds_df_exercise['desired'] = diamonds_df_exercise.apply(is_desired, axis = 'columns')
diamonds_df_exercise.tail()
carat cut color clarity depth table price x y z desired
53935 0.72 Ideal D SI1 60.8 57.0 2757 5.75 5.76 3.50 yes
53936 0.72 Good D SI1 63.1 55.0 2757 5.69 5.75 3.61 no
53937 0.70 Very Good D SI1 62.8 60.0 2757 5.66 5.68 3.56 no
53938 0.86 Premium H SI2 61.0 58.0 2757 6.15 6.12 3.74 no
53939 0.75 Ideal D SI2 62.2 55.0 2757 5.83 5.87 3.64 yes

Eliminación de columnas de un DataFrame#

  • Por último, vamos a ver cómo eliminar columnas de un DataFrame de pandas. Por ejemplo, borraremos las columnas rounded_price y rounded_price_to_100multiple

  • Cargue la biblioteca pandas

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Añadir la columna price_per_carat al DataFrame

diamonds_df['price_per_carat'] = diamonds_df['price']/diamonds_df['carat']
diamonds_df.head()
carat cut color clarity depth table price x y z price_per_carat
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43 1417.391304
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31 1552.380952
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31 1421.739130
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63 1151.724138
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75 1080.645161
  • Utilice la función np.where del paquete numpy de Python:

import numpy as np

diamonds_df['price_per_carat_is_high'] = np.where(diamonds_df['price_per_carat'] > 3500, 1, 0)
diamonds_df.tail()
carat cut color clarity depth table price x y z price_per_carat price_per_carat_is_high
53935 0.72 Ideal D SI1 60.8 57.0 2757 5.75 5.76 3.50 3829.166667 1
53936 0.72 Good D SI1 63.1 55.0 2757 5.69 5.75 3.61 3829.166667 1
53937 0.70 Very Good D SI1 62.8 60.0 2757 5.66 5.68 3.56 3938.571429 1
53938 0.86 Premium H SI2 61.0 58.0 2757 6.15 6.12 3.74 3205.813953 0
53939 0.75 Ideal D SI2 62.2 55.0 2757 5.83 5.87 3.64 3676.000000 1
  • Aplicar una función compleja para redondear el precio de los diamantes hasta su tope:

import math

diamonds_df['rounded_price'] = diamonds_df['price'].apply(math.ceil)
diamonds_df.head()
carat cut color clarity depth table price x y z price_per_carat price_per_carat_is_high rounded_price
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43 1417.391304 0 326
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31 1552.380952 0 326
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31 1421.739130 0 327
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63 1151.724138 0 334
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75 1080.645161 0 335
  • Escribe un código para crear una función definida por el usuario:

import math

def get_100_multiple_ceil(x):
    y = math.ceil(x/100)*100
    return y
 
diamonds_df['rounded_price_to_100multiple']=diamonds_df['price'].apply(get_100_multiple_ceil)
diamonds_df.head()
carat cut color clarity depth table price x y z price_per_carat price_per_carat_is_high rounded_price rounded_price_to_100multiple
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43 1417.391304 0 326 400
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31 1552.380952 0 326 400
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31 1421.739130 0 327 400
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63 1151.724138 0 334 400
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75 1080.645161 0 335 400
  • Eliminar las columnas rounded_price y rounded_price_to_100multiple utilizando la función drop:

diamonds_df = diamonds_df.drop(columns = ['rounded_price', 'rounded_price_to_100multiple'])
diamonds_df.head()
carat cut color clarity depth table price x y z price_per_carat price_per_carat_is_high
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43 1417.391304 0
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31 1552.380952 0
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31 1421.739130 0
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63 1151.724138 0
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75 1080.645161 0

Escribir un DataFrame en un archivo#

  • En este ejercicio, escribiremos un DataFrame de diamantes en un archivo .csv. Para ello, utilizaremos el siguiente código:

  • Cargue la biblioteca pandas

import pandas as pd
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Escriba el conjunto de datos de los diamantes en un archivo .csv:

diamonds_df.to_csv('diamonds_modified.csv')
  • Por defecto, la función to_csv genera un archivo que incluye las cabeceras de las columnas y los números de las filas. así como los números de fila. Añade un parámetro index=False para excluir los números de fila:

diamonds_df.to_csv('diamonds_modified.csv', index = False)
  • Ahora que tenemos una idea básica de cómo cargar y manejar los datos en un objeto DataFrame de pandas, vamos a empezar a hacer algunos gráficos simples a partir de los datos.

  • matplotlib es una biblioteca de trazado disponible en la mayoría de las distribuciones de Python y es la es la base de varios paquetes de ploteo, incluyendo la funcionalidad de ploteo incorporada en pandas y seaborn. matplotlib permite controlar todos los aspectos de una figura y es conocido por ser muy detallado.

Trazado y análisis de un histograma#

  • En este ejercicio, crearemos un histograma de la frecuencia de los diamantes en el conjunto de datos con sus respectivas especificaciones de carat (quilates) en el eje \(x\):

  • Cargue la biblioteca pandas

import pandas as pd
import seaborn as sns
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Trazar un histograma utilizando el conjunto de datos de diamantes donde el eje x axis = carat. El eje \(y\) de este gráfico indica el número de diamantes del conjunto de datos con la especificación de carat en el eje \(x\).

diamonds_df.hist(column='carat');
_images/e52880437881cc9deb0a45a3a8bf44480607e46467f429c9285151f72c7441e0.png
  • La función hist tiene un parámetro llamado bins, que se refiere literalmente al número de intervalos de igual tamaño en los que se dividen los puntos de datos. Por defecto el parámetro bins está fijado en 10 en pandas. Podemos cambiarlo por un número diferente diferente, si lo deseamos.

diamonds_df.hist(column = 'carat', bins = 50);
_images/caec701f20ff1f532000a0a4373eeb9640a918e42b0e30850840e211c3347853.png
  • Ahora, veamos la misma función utilizando seaborn. Note que pandas establece el parámetro bins a un valor por defecto de 10, pero seaborn infiere un bin de tamaño apropiado basado en la distribución estadística del conjunto de datos.

import seaborn as sns

sns.distplot(diamonds_df.carat);
_images/b3cbad605429ee3acf804b885e0d4e6439d65b74c996c126de99dad6b4e309ee.png
  • Por defecto, la función distplot también incluye una curva suavizada sobre el histograma, llamada estimación de la densidad del kernel (KDE). Si queremos eliminar el KDE y mirar sólo el histograma, podemos utilizar el parámetro kde=False.

sns.distplot(diamonds_df.carat, kde = False);
_images/0c749549e00c84e8e2de0a945ee455583ecd37de55b7891177e84fc1ab11d2a3.png
  • Una transformación logarítmica ayuda a identificar más tendencias. Por ejemplo, en el siguiente gráfico, el eje \(x\) muestra los valores transformados en logaritmos de la variable del precio, y vemos que hay dos picos que indican dos tipos de diamantes: uno con un precio alto y otro con un precio bajo

import numpy as np
sns.distplot(np.log(diamonds_df.price));
_images/c897f4dcd76164c8aea835c9f24a65d24ee4fdad1f52ae06f86d1de757b6586f.png

Qué valores de las características son más frecuentes en el conjunto de datos (en este caso, hay un pico en torno a 6.8 y otro pico entre 8.5 y 9, nótese que log(price) = valores, en este caso

Creación de un gráfico de barras y cálculo de la distribución del precio medio#

  • En este ejercicio, aprenderemos a crear una tabla utilizando la función pandas crosstab. Utilizaremos una tabla para generar un gráfico de barras. A continuación, exploraremos un gráfico de barras generado con la biblioteca seaborn y calcularemos la distribución del precio medio. Para ello, vamos a realizar los siguientes pasos

  • Cargue la biblioteca pandas

import pandas as pd
import seaborn as sns
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Imprime los valores únicos de la columna corte:

diamonds_df.cut.unique()
array(['Ideal', 'Premium', 'Good', 'Very Good', 'Fair'], dtype=object)
  • Imprime los valores únicos de la columna claridad:

diamonds_df.clarity.unique()
array(['SI2', 'SI1', 'VS1', 'VS2', 'VVS2', 'VVS1', 'I1', 'IF'],
      dtype=object)
  • unique() devuelve un array. Hay cinco cualidades únicas de cut y ocho valores únicos en clarity. El número de valores únicos se puede obtener utilizando nunique() en `pandas.

  • Para obtener los recuentos de diamantes de cada calidad de cut, primero creamos una tabla utilizando la función pandas crosstab():

cut_count_table = pd.crosstab(index = diamonds_df['cut'], columns = 'count')
cut_count_table
col_0 count
cut
Fair 1610
Good 4906
Ideal 21551
Premium 13791
Very Good 12082
  • Pase estos recuentos a otra función pandas, plot(kind=’bar’):

cut_count_table.plot(kind = 'bar');
_images/3a8d751f3e3206c79c767ddd1f1ea53f5105908eded9c60bc8002ac85257b47c.png

Vemos que la mayoría de los diamantes del conjunto de datos son de la calidad de corte Ideal, seguidos de Premium, Very Good, Good y Fair. Ahora, veamos cómo generar el mismo gráfico utilizando seaborn.

  • Generate the same bar plot using seaborn

diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
sns.catplot(data = diamonds_df, x = 'cut', aspect = 1.5, kind = "count", color = "b");
_images/4a82a6eb53aaf8fd5a1d795c8450fe7ecc5e429c1998c5f37586b86f2a470a2a.png

Observe cómo la función catplot() no requiere que creemos la tabla de recuento intermedia (utilizando pd.crosstab()), y reduce un paso en el proceso de trazado.

  • A continuación, se muestra cómo se obtiene la distribución del precio medio de las diferentes calidades de cut utilizando seaborn

import seaborn as sns
from numpy import median, mean

sns.set(style = "whitegrid")
ax = sns.barplot(x = "cut", y = "price", data = diamonds_df, estimator = mean);
_images/316d9476a26e1f5ff8c4f1482bcde9f8b5fc7ced6b3d89ecb6b1d99169ddecb5.png

Aquí, las líneas negras (barras de error) de los rectángulos indican la incertidumbre (o dispersión de los valores) en torno a la estimación de la media. Las funciones mencionadas van mucho más allá de un simple recuento: aplican una función que calcula una medida de tendencia central (por defecto es el valor medio) y muestran, aplicando bootstrapping, el intervalo de confianza del 95% para dicha medida. Por defecto, este valor está fijado en un 95% de confianza. ¿Cómo lo cambiamos? Utilizando el parámetro ci=68, por ejemplo, lo fijamos en el 68%. También podemos representar la desviación estándar en los precios utilizando ci=sd.

  • Reordenar las barras del eje x utilizando el orden:

ax = sns.barplot(x = "cut", y = "price", data = diamonds_df, estimator = mean, ci = 68, 
                 order=['Ideal','Good','Very Good','Fair','Premium']);
_images/f8041e6906bf300bd1019aad5444c9f02e4c32fe7e99336e20b144bcb0559025.png

Creación de gráficos de barras agrupados por una característica específica#

  • En este ejercicio, utilizaremos el conjunto de datos de los diamantes para generar la distribución de los precios con respecto al color para cada calidad de corte. En el ejercicio 7, vimos la distribución de precios para diamantes de diferentes calidades de talla. Ahora, nos gustaría ver la variación de cada color:

  • Cargue la biblioteca pandas

import pandas as pd
import seaborn as sns
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.tail()
carat cut color clarity depth table price x y z
53935 0.72 Ideal D SI1 60.8 57.0 2757 5.75 5.76 3.50
53936 0.72 Good D SI1 63.1 55.0 2757 5.69 5.75 3.61
53937 0.70 Very Good D SI1 62.8 60.0 2757 5.66 5.68 3.56
53938 0.86 Premium H SI2 61.0 58.0 2757 6.15 6.12 3.74
53939 0.75 Ideal D SI2 62.2 55.0 2757 5.83 5.87 3.64
  • Utilice el parámetro hue para trazar grupos anidados:

ax = sns.barplot(x = "cut", y = "price", hue = 'color', data = diamonds_df);
_images/0b04482180b5ab8db201ee5fcbbb4336bcb9394fd9e8c06b7205ee59c6912fd1.png

Aquí podemos observar que los patrones de precios de los diamantes de diferentes colores son similares para cada calidad de talla.

Cómo ajustar los parámetros de un gráfico de barras agrupadas#

  • En este ejercicio, modificaremos los parámetros de los gráficos, por ejemplo, hue, de un gráfico de barras agrupadas. Veremos cómo colocar las leyendas y las etiquetas de los ejes en los lugares adecuados y también exploraremos la función de rotación

  • Cargue la biblioteca pandas

import pandas as pd
import seaborn as sns
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
ax = sns.barplot(x = "cut", y = "price", hue = 'color', data = diamonds_df);
_images/f32524c2f89ba6295f8ec3fedf1c66ac8a89e513f319313150b8a975b9544059.png
ax = sns.barplot(x='cut', y='price', hue='color', data=diamonds_df)
ax.legend(loc='upper right', ncol=4);
_images/4840eb97309846397fae453f9da08025d258bb2aa7ec50a2b37f46a4d0afff61.png

En la llamada anterior a ax.legend(), el parámetro ncol denota el número de columnas en las que deben organizarse los valores de la leyenda, y el parámetro loc especifica la ubicación de la leyenda y puede tomar cualquiera de los ocho valores 'upper left', 'upper right', 'lower left', 'lower right'.

  • Para modificar las etiquetas de los ejes \(𝑥\) y \(𝑦\), introduzca el siguiente código

ax = sns.barplot(x='cut', y='price', hue='color', data=diamonds_df)
ax.legend(loc='upper right', ncol=4)
ax.set_xlabel('Cut', fontdict={'fontsize' : 12})
ax.set_ylabel('Price', fontdict={'fontsize' : 12});
_images/5e8bd82accdecc7598dac6df360932d4f6fb80fa7a876da6deb98133ab8ff966.png
  • Del mismo modo, utilice esto para modificar el tamaño de la fuente y la rotación del eje \(x\) de la garrapata etiquetas:

ax = sns.barplot(x='cut', y='price', hue='color', data=diamonds_df)
ax.legend(loc='upper right',ncol=4)
ax.set_xticklabels(ax.get_xticklabels(), fontsize=13, rotation=45)
ax.set_xlabel('Cut', fontdict={'fontsize' : 12})
ax.set_ylabel('Price', fontdict={'fontsize' : 12});
_images/42fcda5bb83e7882e6884440ff0b30051905a3b9d1c0af0f62b31b902975fe4c.png

La función de rotación es especialmente útil cuando las etiquetas de ticks son largas y se amontonan en el eje \(x\).

Anotar un gráfico de barras#

  • En este ejercicio, anotaremos un gráfico de barras, generado con la función catplot de seaborn, utilizando una nota justo encima del gráfico.

  • Cargue la biblioteca pandas

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
  • Leer los archivos de la URL en el DataFrame de pandas

diamonds_df = pd.read_csv(diamonds_url)
diamonds_df.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
1 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31
2 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31
3 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63
4 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75
  • Generar un gráfico de barras utilizando la función catplot de la biblioteca seaborn

ax = sns.catplot(data=diamonds_df, x="cut", aspect=1.5, kind="count", color="b");
_images/6ebe0d8e54b1ea30d666f914d86da36a678ccc45a9644fcdc678af63e80e0a24.png
  • Anote la columna que pertenece a la categoría Ideal:

ideal_group = diamonds_df.loc[diamonds_df['cut']=='Ideal']
ideal_group.head()
carat cut color clarity depth table price x y z
0 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43
11 0.23 Ideal J VS1 62.8 56.0 340 3.93 3.90 2.46
13 0.31 Ideal J SI2 62.2 54.0 344 4.35 4.37 2.71
16 0.30 Ideal I SI2 62.0 54.0 348 4.31 4.34 2.68
39 0.33 Ideal I SI2 61.8 55.0 403 4.49 4.51 2.78
  • Encuentre la ubicación de la coordenada \(x\) donde debe colocarse la anotación:

x = ideal_group.index.tolist()[0]
  • Encuentre la ubicación de la coordenada \(y\) donde debe colocarse la anotación:

y = len(ideal_group)
  • Imprime la ubicación de las coordenadas \(x\) e \(y\):

print(x)
print(y)
0
21551
  • Anota la gráfica con una nota:

sns.catplot(data=diamonds_df, x="cut", aspect=1.5, kind="count", color="b")
plt.annotate('excellent polish and symmetry ratings;\nreflects almost all the light that enters it', 
             xy=(x,y), xytext=(x+0.3, y+2000), arrowprops=dict(facecolor='red'));
_images/334f108b76853041a87337a4e38bcfa335fab0423284ca3422d68e4426ab60ae.png
  • Ahora, parece que hay muchos parámetros en la función de anotación. La documentación oficial de Matplotlib cubre todos los detalles

Ejercicio para entregar#

  • Trabajaremos con el conjunto de datos de 120 años de historia olímpica adquirido por Randi Griffin en Randi-Griffin y puesto a disposición en athlete_events. - Su tarea consiste en identificar los cinco deportes más importantes según el mayor número de medallas otorgadas en el año 2016, y luego realizar el siguiente análisis:

  1. Genere un gráfico que indique el número de medallas concedidas en cada uno de los cinco principales deportes en 2016.

  2. Trace un gráfico que represente la distribución de la edad de los ganadores de medallas en los cinco principales deportes en 2016.

  3. Descubre qué equipos nacionales ganaron el mayor número de medallas en los cinco principales deportes en 2016.

  4. Observe la tendencia del peso medio de los atletas masculinos y femeninos ganadores en los cinco principales deportes en 2016

  • Pasos principales

  1. Descargue el conjunto de datos y formatéelo como un DataFrame de pandas.

  2. Filtra el DataFrame para incluir solo las filas correspondientes a los ganadores de medallas de 2016.

  3. Descubre las medallas concedidas en 2016 en cada deporte.

  4. Enumera los cinco deportes más importantes en función del mayor número de medallas concedidas. Filtra el DataFrame una vez más para incluir solo los registros de los cinco deportes principales en 2016.

  5. Genere un gráfico de barras con los recuentos de registros correspondientes a cada uno de los cinco deportes principales.

  6. Generar un histograma para la característica Edad de todos los ganadores de medallas en los cinco deportes principales (2016).

  7. Genera un gráfico de barras que indique cuántas medallas ganó el equipo de cada país en los cinco deportes principales en 2016.

  8. Genere un gráfico de barras que indique el peso medio de los jugadores, clasificados en función del género, que ganaron en los cinco principales deportes en 2016.