Curso de introducción a la programación con Python¶

    Autor: Luis Fernando Apáez Álvarez
    -Curso PyM-
    Clase 1: Librería Seaborn
    Fecha: 08 de diciembre del 2022


Contenido¶

  • Primeros pasos
    • Diagrama de dispersión
    • Gráfico de conteo
  • Gráficos relacionales: replot()
    • Diagramas de dispersión
    • Configuraciones de un gráfico
  • Gráficos de líneas
    • Librería yfinance
    • Graficando precios de acciones

Primeros pasos ¶

La librería seaborn es utilizada para las visualizaciones en python, es muy similar a la librería matplotlib, de hecho seaborn está construido a partir de dicha librería. Las visualizaciones dentro del análisis de datos nos sirven para explorar los datos y para, en la etapa final, comunicar los resultados.

Diagrama de dispersión¶

Como hemos visto en alguna clase anterior, podemos cargar conjuntos de datos a partir de la librería seaborn:

In [4]:
import seaborn as sns
import matplotlib.pyplot as plt

# cargamos el conjunto de datos iris
df_iris = sns.load_dataset('iris')
df_iris.head()
Out[4]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

Procedemos a realizar un gráfico de dispersión escribiendo:

In [5]:
# primero especificamos el conjunto de datos (data=)
# y despues definimos las variables del eje x y el eje y
sns.scatterplot(data=df_iris, x='petal_width', y='petal_length')
plt.show()

Gráfico de conteo¶

Este tipo de gráficos toman valores categóricos y devuelven barras que representan el número de entradas de cada categoría. Podemos crear un gráfico de conteo para ver cuántos elementos tenemos en nuestro conjunto de datos por especie

In [6]:
# conjunto de datos: data=
# variable categorica: x=
sns.countplot(data=df_iris, x='species')
plt.show()

Luego, retomando el diagrama de dispersión que hicimos antes, podemos agregar colores a los puntos de dicho diagrama, donde la manera de colorear dependera de la especie de la que se trate. Lo anterior lo conseguiremos agregando el parámetro hue= a la función scatterplot(), donde configuraremos hue='species' para hacer que el coloreado se haga con base en la columna species:

In [7]:
sns.scatterplot(data=df_iris, x='petal_width', y='petal_length', hue='species')
plt.show()

Notamos que en la parte donde se muestran las etiquetas, se muestra primero la especie setosa. Podemos cambiar ese orden:

In [8]:
sns.scatterplot(data=df_iris, x='petal_width', y='petal_length', 
                hue='species',
                # cambiaremos el orden en el que se muestran
                # las etiquetas 
                hue_order=['virginica', 'setosa', 'versicolor'])
plt.show()

Asimismo, vemos que los colores se han asignado de manera automática. Para cambiar los colores necesitaremos definir un diccionario donde las llaves son los nombres de la categoría y los valores son los colores que queremos asignarles. Luego, dicho diccionario será pasado a un nuevo parámetro denominada palette:

In [10]:
# diccionario
dict_color = {'setosa': 'blue',
              'versicolor': 'red',
              'virginica': 'green'}

sns.scatterplot(data=df_iris, x='petal_width', y='petal_length', 
                hue='species',
                # cambiaremos el orden en el que se muestran
                # las etiquetas 
                hue_order=['virginica', 'setosa', 'versicolor'],
                # cambiamos los colores
                palette=dict_color)
plt.show()

Gráficos relacionales: replot() ¶

Del gráfico anterior vemos que en un mismo diagrama de dispersión hemos colocado la información de las tres categorías en cuestión. En realidad podemos obtener un gráfico por cada categoría, lo cual conseguiremos con la función relplot(). La gran ventaja de dicha función es crear subgráficos en una misma figura.

Diagramas de dispersión¶

Comenzaremos con realizar un diagrama de dispersión como el anterior, pero utilizando ahora la función relplot():

In [16]:
sns.relplot(data=df_iris, x='petal_width', y='petal_length', 
            hue='species',
            palette=dict_color,
            kind='scatter')
plt.show()

vemos que el código es prácticamente el mismo, pero ahora configuramos un nuevo parámetro kind= para especificar el tipo de gráfico.

Ahora, obtengamos varios diagramas de dispersión, uno por cada especie

In [17]:
sns.relplot(data=df_iris, x='petal_width', y='petal_length', 
            hue='species',
            palette=dict_color,
            kind='scatter',
            # obtendremos un diagrama de dispersion por especie
            # organizados por columnas
            col='species')
plt.show()
In [18]:
sns.relplot(data=df_iris, x='petal_width', y='petal_length', 
            hue='species',
            palette=dict_color,
            kind='scatter',
            # obtendremos un diagrama de dispersion por especie
            # organizados por filas
            row='species')
plt.show()

Podemos utilizar row y col al mismo tiempo. Para ver un ejemplo de ello carguemos un nuevo conjunto de datos

In [19]:
df_tips = sns.load_dataset('tips')
df_tips
Out[19]:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
... ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3
240 27.18 2.00 Female Yes Sat Dinner 2
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2
243 18.78 3.00 Female No Thur Dinner 2

244 rows × 7 columns

In [21]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            kind='scatter',
            # hora del dia (almuerzo o cena)
            row='time',
            # estado del fumador
            col='smoker')
plt.show()

Con lo cual conseguimos un subgráfico para cada combinación de las variables categóricas time y smoker. Como otro ejemplo, podemos ver los diagramas de dispersión de total_bill versus tip para cada día de la semana

In [22]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            kind='scatter',
            # hora del dia (almuerzo o cena)
            col='day')
plt.show()

Puede parecer que los gráficos anteriores están demasiado juntos. Así, podemos configurar el número de subgráficos por fila:

In [23]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            kind='scatter',
            # hora del dia (almuerzo o cena)
            col='day',
            # configuramos 2 graficos por fila
            col_wrap=2)
plt.show()

Y podemos cambiar el orden en que se muestran los gráficos

In [24]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            kind='scatter',
            # hora del dia (almuerzo o cena)
            col='day',
            # configuramos 2 graficos por fila
            col_wrap=2,
            # cambiamos el orden en el que se muestran
            # los graficos
            col_order=['Sun', 'Sat', 'Fri', 'Thur'])
plt.show()

Configuraciones de un gráfico¶

Ahora veremos algunos aspectos en los cuales modificaremos las visualizaciones de nuestros gráficos.

Aumentaremos el tamaño de los puntos del diagrama de dispersión con base en los valores de la columna size

In [30]:
df_tips.head()
Out[30]:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
In [29]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            # aumentamos el tamagnio de los puntos
            # con base en la columna size
            size='size',
            kind='scatter')
plt.show()

Dado a que los puntos son del mismo color puede hacerse un poco difícil realizar alguna interpretación, por ello configuraremos el color de los puntos de acuerdo a la columna size

In [31]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            # aumentamos el tamagnio de los puntos
            # con base en la columna size
            size='size',
            # configuramos el color de acuerdo a la columna
            # size
            hue='size',
            kind='scatter')
plt.show()

con lo que conseguimos un gráfico más estético y que nos brinda mayor información.

Luego, en vez de utilizar el color y el tamaño como distintivo de las distintas categorías, podemos utilizar el color y el tipo de punto:

In [32]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            # cambiamos el tipo de puntos
            # con base en la columna smoker
            style='smoker',
            # configuramos el color de acuerdo a la columna
            # smoker
            hue='smoker',
            kind='scatter')
plt.show()

Finalmente, podemos configurar la transparencia de los puntos

In [34]:
sns.relplot(data=df_tips, x='total_bill', y='tip', 
            # cambiamos el tipo de puntos
            # con base en la columna smoker
            style='smoker',
            # configuramos el color de acuerdo a la columna
            # smoker
            hue='smoker',
            # haremos mas transparentes los puntos
            alpha=0.4,
            # y podemos cambiar los colores como habiamos visto
            # antes
            palette={'Yes': 'red', 'No': 'blue'},
            kind='scatter')
plt.show()

Gráficos de líneas ¶

Este tipo de gráficos son muy útiles y usados en series de tiempo, o básicamente en datos que dependen del tiempo.

Librería yfinance¶

Para los siguientes ejemplos cargaremos datos sobre los precios históricos de las acciones de Apple, para lo cual utilizaremos la librería yfinance. Dicha librería obtiene información sobre los principales mercados financieros del mundo y extrae la información proveniente de yahoo finance. Así

In [35]:
# Importacione necesaria
import yfinance as yf

# Accedemos a la informacion de apple con la funcion Ticker()
# donde dentro de dicha funcion colocamos la clave de apple
apple = yf.Ticker('aapl')

# Extraemos la informacion de los precios diarios (interval='1d')
# del 2016-01-01 al 2021-05-10 y reseteamos el indice por defecto.
# Cabe resaltar que lo que obtenemos de la funcion history() es
# un dataframe
df_apple = apple.history(interval='1d', start='2016-01-01', end='2021-05-10').reset_index()
df_apple.head()
Out[35]:
Date Open High Low Close Volume Dividends Stock Splits
0 2016-01-04 23.484390 24.116072 23.344779 24.111494 270597600 0.0 0.0
1 2016-01-05 24.203049 24.225935 23.438622 23.507282 223164000 0.0 0.0
2 2016-01-06 23.015209 23.429466 22.857290 23.047251 273829600 0.0 0.0
3 2016-01-07 22.584929 22.916790 22.069970 22.074547 324377600 0.0 0.0
4 2016-01-08 22.555181 22.683348 22.145503 22.191277 283192000 0.0 0.0
In [36]:
# volvemos a resetear el indice
df_apple = df_apple.reset_index()
In [37]:
df_apple.head()
Out[37]:
index Date Open High Low Close Volume Dividends Stock Splits
0 0 2016-01-04 23.484390 24.116072 23.344779 24.111494 270597600 0.0 0.0
1 1 2016-01-05 24.203049 24.225935 23.438622 23.507282 223164000 0.0 0.0
2 2 2016-01-06 23.015209 23.429466 22.857290 23.047251 273829600 0.0 0.0
3 3 2016-01-07 22.584929 22.916790 22.069970 22.074547 324377600 0.0 0.0
4 4 2016-01-08 22.555181 22.683348 22.145503 22.191277 283192000 0.0 0.0

Podemos realizar un gráfico de dispersión del tiempo (el cual representaremos mediante la columna index) versus la columna Open (precio de apertura de las acciones de Apple):

In [38]:
sns.relplot(data=df_apple, x='index', y='Open', 
            kind='scatter')
plt.show()

Si bien se describe el comportamiento general de las variables en cuestión, como se dijo antes, los gráficos de líneas permite una mejor visualización para datos que dependen del tiempo. Crearemos entonces un gráfico de líneas:

In [39]:
sns.relplot(data=df_apple, x='index', y='Open', 
            # cambiamos ahora a kind='line'
            kind='line')
plt.show()

Con lo cual obtenemos nuestro gráfico de líneas que representa de mejor manera el comportamiento de nuestros datos.

Para continuar con un ejemplo, primero modificaremos el dataframe de los precios de Apple

In [43]:
# Por simplicidad solo nos quedaremos con las siguientes columnas
df_apple = df_apple[['index', 'Date', 'Open']]
df_apple.head()
Out[43]:
index Date Open
0 0 2016-01-04 23.484390
1 1 2016-01-05 24.203049
2 2 2016-01-06 23.015209
3 3 2016-01-07 22.584929
4 4 2016-01-08 22.555181

Graficando precio de acciones¶

Luego, extraeremos ahora información sobre más compañias y modificaremos dichos dataframes para que queden de la misma forma que el dataframe anterior. Para ello, para mayor facilidad crearemos una función:

In [47]:
def info_acciones(clave):
    # accedemos a la informacion de la compañia dependiendo
    # de la clave
    comp = yf.Ticker(clave)
    # Extraemos la informacion de los precios diarios (interval='1d')
    # del 2016-01-01 al 2021-05-10 y reseteamos el indice por defecto.
    # Cabe resaltar que lo que obtenemos de la funcion history() es
    # un dataframe
    df = comp.history(interval='1d', start='2016-01-01', end='2021-05-10').reset_index()
    # volvemos a resetear el indice
    df = df.reset_index()
    # Por simplicidad solo nos quedaremos con las siguientes columnas
    df = df[['index', 'Date', 'Open']]
    # Retornamos el dataframe anterior
    return df

Ahora obtendremos los precios de las acciones de Google, Tesla y Microsoft (puedes ver las claves o símbolos de dichas compañias, y de más compañias, yendo al siguiente Link)

In [48]:
df_google = info_acciones('goog')
df_tesla = info_acciones('tsla')
df_microsoft = info_acciones('msft')

display(df_google.head(2))
display(df_tesla.head(2))
display(df_microsoft.head(2))
index Date Open
0 0 2016-01-04 37.150002
1 1 2016-01-05 37.322498
index Date Open
0 0 2016-01-04 15.381333
1 1 2016-01-05 15.090667
index Date Open
0 0 2016-01-04 48.700350
1 1 2016-01-05 49.247247

Luego, para cada dataframe correspondiente a las 4 compañias con las que estamos trabajando, agregaremos una columna nueva:

In [49]:
# El nombre de la columna nueva para cada dataframe debe ser el mismo
df_apple['Compañia'] = ['Apple' for i in range(df_apple.shape[0])]
df_google['Compañia'] = ['Google' for i in range(df_apple.shape[0])]
df_tesla['Compañia'] = ['Tesla' for i in range(df_apple.shape[0])]
df_microsoft['Compañia'] = ['Microsoft' for i in range(df_apple.shape[0])]
In [50]:
# veamos el dataframe de apple
df_apple.head()
Out[50]:
index Date Open Compañia
0 0 2016-01-04 23.484390 Apple
1 1 2016-01-05 24.203049 Apple
2 2 2016-01-06 23.015209 Apple
3 3 2016-01-07 22.584929 Apple
4 4 2016-01-08 22.555181 Apple

Finalmente, aplicaremos los 4 dataframes en uno solo utilizando la función pd.concat()

In [51]:
import pandas as pd

df_gral = pd.concat([df_apple, df_google, df_tesla, df_microsoft])
df_gral.head()
Out[51]:
index Date Open Compañia
0 0 2016-01-04 23.484390 Apple
1 1 2016-01-05 24.203049 Apple
2 2 2016-01-06 23.015209 Apple
3 3 2016-01-07 22.584929 Apple
4 4 2016-01-08 22.555181 Apple

Resetearemos el índice y sólo nos quedaremos con las mismas cuatro columnas anteriores

In [60]:
df_gral = df_gral.reset_index()[['index', 'Date', 'Open', 'Compañia']]
df_gral.head()
Out[60]:
index Date Open Compañia
0 0 2016-01-04 23.484390 Apple
1 1 2016-01-05 24.203049 Apple
2 2 2016-01-06 23.015209 Apple
3 3 2016-01-07 22.584929 Apple
4 4 2016-01-08 22.555181 Apple
In [61]:
# Vemos que tenemos 1346 registros por cada compañia
df_gral.value_counts('Compañia')
Out[61]:
Compañia
Apple        1346
Google       1346
Microsoft    1346
Tesla        1346
dtype: int64
In [63]:
# los nombres de las columna
df_gral.columns
Out[63]:
Index(['index', 'Date', 'Open', 'Compañia'], dtype='object')
In [74]:
# cambiamos el nombre de la columna index por id
df_gral = df_gral.rename(columns={'index': 'id'})

# veamos que tenemos 4 valores para cada id
df_gral[df_gral.id == 0]
Out[74]:
id Date Open Compañia
0 0 2016-01-04 23.484390 Apple
1346 0 2016-01-04 37.150002 Google
2692 0 2016-01-04 15.381333 Tesla
4038 0 2016-01-04 48.700350 Microsoft

Ahora bien, podemos realizar un gráfico de líneas por cada compañia, pero para ello configuraremos los parámetros de hue y style como hemos visto en ejemplos anteriores

In [76]:
sns.relplot(data=df_gral, x='id', y='Open',
            # configuracion de acuerdo a la columna
            # Compañia
            style='Compañia',
            hue='Compañia',
            kind='line')
plt.show()

Podemos configurar markers=True para observar los puntos del diagrama de dispersión correspondiente, junto con los diagramas de líneas:

In [78]:
sns.relplot(data=df_gral, x='id', y='Open',
            # configuracion de acuerdo a la columna
            # Compañia
            style='Compañia',
            hue='Compañia',
            # mostramos los puntos
            markers=True,
            kind='line')
plt.show()

donde el estilo de los puntos varía de acuerdo a cada subgrupo.

Si no queremos visualizar los distintos tipos de líneas configuramos

In [79]:
sns.relplot(data=df_gral, x='id', y='Open',
            # configuracion de acuerdo a la columna
            # Compañia
            style='Compañia',
            hue='Compañia',
            # mostramos los puntos
            markers=True,
            # configuramos para que no se vean los 
            # estilos de lineas
            dashes=False,
            kind='line')
plt.show()

Por otro lado, recordemos que para cada id tenemos 4 valores asignados

In [81]:
# veamos que tenemos 4 valores para cada id
df_gral[df_gral.id == 0]
Out[81]:
id Date Open Compañia
0 0 2016-01-04 23.484390 Apple
1346 0 2016-01-04 37.150002 Google
2692 0 2016-01-04 15.381333 Tesla
4038 0 2016-01-04 48.700350 Microsoft
In [82]:
# veamos que tenemos 4 valores para cada id
df_gral[df_gral.id == 1]
Out[82]:
id Date Open Compañia
1 1 2016-01-05 24.203049 Apple
1347 1 2016-01-05 37.322498 Google
2693 1 2016-01-05 15.090667 Tesla
4039 1 2016-01-05 49.247247 Microsoft

Podemos realizar un gráfico de líneas para las columnas id y Open, pero ahora cada id tiene asignados 4 valores posibles. En ejemplo anteriores cada, digamos, id tenía asociados un único valor.

Antes de realizar el gráfico de líneas que mencionamos antes, veamos su gráfico de dispersión

In [83]:
sns.relplot(data=df_gral, x='id', y='Open',
            kind='scatter')
plt.show()

Por otro lado, al graficar el gráfico de líneas lo que ocurrirá es que los distintos valores de Open para un mismo id serán agregados a una sola medida, por defecto dicha medida será el promedio. Así

In [80]:
sns.relplot(data=df_gral, x='id', y='Open',
            kind='line')
plt.show()

donde vemos que el gráfico de líneas que visualizamos corresponde a los precios promedios de las acciones de las 4 compañias, y además se grafica de manera automática un intervalo de confianza para la media.

Podemos configurar que el área sombreada represente la desviación estándar en vez de los intervalos de confianza:

In [84]:
sns.relplot(data=df_gral, x='id', y='Open',
            ci='sd',
            kind='line')
plt.show()

Y también podemos desactivar la visualización del intervalo de confianza

In [85]:
sns.relplot(data=df_gral, x='id', y='Open',
            ci=None,
            kind='line')
plt.show()