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

    Autor: Luis Fernando Apáez Álvarez
    -Curso PyM-
    Clase 4: Gráficos en pandas
    Fecha: 05 de diciembre del 2022


Contenido¶

  • Recapitulación
    • Método unique()
    • Método value_counts()
    • Eliminación de filas y columnas
    • Método replace()
    • Elementos importantes
  • Graficación con pandas
    • Diagramas de dispersión
    • Histogramas

Inicialmente en esta clase recapitularemos algunos conceptos sobre pandas que se abordaron en el proyecto resuelto de la clase 2, los cuales son muy importantes y por ende los volveremos a ver, al inicio, de esta clase.

Recapitulación ¶

Utilizaremos la librería seaborn (la cual es muy parecida con matplotlib y la cual está destinada a la graficación) para obtener conjuntos de datos con los cuales trabajar. Para ello:

In [1]:
# importacion necesaria
import seaborn as sns

# veamos los nombres de todos los conjuntos de datos
# que se disponen en dicha libreria
sns.get_dataset_names()
Out[1]:
['anagrams',
 'anscombe',
 'attention',
 'brain_networks',
 'car_crashes',
 'diamonds',
 'dots',
 'dowjones',
 'exercise',
 'flights',
 'fmri',
 'geyser',
 'glue',
 'healthexp',
 'iris',
 'mpg',
 'penguins',
 'planets',
 'seaice',
 'taxis',
 'tips',
 'titanic']

Trabajaremos con el conjunto iris. Para cargar ese conjunto de datos utilizamos el método load_dataset() como sigue

In [80]:
df = sns.load_dataset("iris")
df.head()
Out[80]:
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

Método unique()¶

El método unique() actúa sobre una columna (serie) y nos devuelve los valores distintos que hay en dicha columna, por ejemplo

In [3]:
df.species.unique()
Out[3]:
array(['setosa', 'versicolor', 'virginica'], dtype=object)

nos dice que en la columna species solo hay 4 valores únicos, los cuales son las especies.

Método value_counts()¶

Este método agrupará de manera automática los distintos valores únicos de una columna determinada y después contará el número de apariciones de esos valores únicos en la columna correspondiente. Por ejemplo, si utilizamos el método value_counts_() sobre la columna species lo que pasará es que se considerará inicialmente los valores únicos ['setosa', 'versicolor', 'virginica'] y después se contará cuántas filas tienen asociado el valor setosa, cuántas filas tienen asociado el valor virginica y cuántos el valor versicolor. Así:

In [5]:
df.species.value_counts()
Out[5]:
setosa        50
versicolor    50
virginica     50
Name: species, dtype: int64

lo que nos dice que tenemos 50 filas de cada especie. De manera totalmente alternativa podemos escribir

In [6]:
df.value_counts('species')
Out[6]:
species
setosa        50
versicolor    50
virginica     50
dtype: int64

Eliminación de filas o columnas¶

Para elminar filas o columnas de un dataframe utilizamos el método drop() de dos posibles maneras:

In [9]:
# eliminacion de una fila:
# eliminaremos la primer fila
df.drop(0, axis=0).head()
Out[9]:
sepal_length sepal_width petal_length petal_width species
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
5 5.4 3.9 1.7 0.4 setosa

notamos que la fila que tenía el índice 0 ya no se ve. Podemos eliminar más de una fila a la vez

In [11]:
# eliminamos las primeras tres filas
df.drop([0,1,2], axis=0).head()
Out[11]:
sepal_length sepal_width petal_length petal_width species
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 5.4 3.9 1.7 0.4 setosa
6 4.6 3.4 1.4 0.3 setosa
7 5.0 3.4 1.5 0.2 setosa
In [12]:
# eliminamos las primeras 10 filas
df.drop([i for i in range(10)], axis=0).head()
Out[12]:
sepal_length sepal_width petal_length petal_width species
10 5.4 3.7 1.5 0.2 setosa
11 4.8 3.4 1.6 0.2 setosa
12 4.8 3.0 1.4 0.1 setosa
13 4.3 3.0 1.1 0.1 setosa
14 5.8 4.0 1.2 0.2 setosa

o también podemos eliminar columnas, para lo cual cambiaremos el parámetro de axis=0 al de axis=1:

In [13]:
# eliminacion de una columna:
# eliminaremos la primer columna
df.drop('sepal_length', axis=1).head()
Out[13]:
sepal_width petal_length petal_width species
0 3.5 1.4 0.2 setosa
1 3.0 1.4 0.2 setosa
2 3.2 1.3 0.2 setosa
3 3.1 1.5 0.2 setosa
4 3.6 1.4 0.2 setosa
In [14]:
# eliminaremos dos columnas a la vez
df.drop(['sepal_length', 'species'], axis=1).head()
Out[14]:
sepal_width petal_length petal_width
0 3.5 1.4 0.2
1 3.0 1.4 0.2
2 3.2 1.3 0.2
3 3.1 1.5 0.2
4 3.6 1.4 0.2

Método replace()¶

Supongamos que queremos agregar una columna nueva de la siguiente manera: si la especie es setosa, entonces en la columna nueva colocaremos un 1; si la especie es versicolor colocaremos un 2 y si la especie es virginica colocaremos un 3.

En pandas podemos realizar este tipo de "reemplazos" de valores mediante el método replace(). Este método lo que hace es cambiar los valores de una columna por nuevos valores que nosotros especifiquemos. De tal manera, de acuerdo a lo que queremos hacer deberemos de crear primero una columna nueva como sigue

In [16]:
# Creamos una columna como copia de la columna specie
df['species_num'] = df.species
df.head()
Out[16]:
sepal_length sepal_width petal_length petal_width species species_num
0 5.1 3.5 1.4 0.2 setosa setosa
1 4.9 3.0 1.4 0.2 setosa setosa
2 4.7 3.2 1.3 0.2 setosa setosa
3 4.6 3.1 1.5 0.2 setosa setosa
4 5.0 3.6 1.4 0.2 setosa setosa

Después utilizaremos el método replace() para realizar los cambios numéricos que mencionamos. Para ello, inicialmente, creamos un diccionario con los valores de la columna species_num, dichos valores serán las llaves de ese diccionario, y después, a esas llaves, les asociaremos los valores a sustituir. Esto es

In [21]:
dict_valor = {'setosa': 1, 'versicolor': 2, 'virginica': 3}

Después, pasaremos ese diccionario al método replace(), pero deberemos pasarlo como sigue:

In [22]:
#                 nombre de la  |diccionario con los  
#                 columna       |valores a reemplazar
dict_reemplazo = {'species_num': dict_valor}
In [23]:
# pasamos el diccionario anterior al metodo replace()
df = df.replace(dict_reemplazo)
df
Out[23]:
sepal_length sepal_width petal_length petal_width species species_num
0 5.1 3.5 1.4 0.2 setosa 1
1 4.9 3.0 1.4 0.2 setosa 1
2 4.7 3.2 1.3 0.2 setosa 1
3 4.6 3.1 1.5 0.2 setosa 1
4 5.0 3.6 1.4 0.2 setosa 1
... ... ... ... ... ... ...
145 6.7 3.0 5.2 2.3 virginica 3
146 6.3 2.5 5.0 1.9 virginica 3
147 6.5 3.0 5.2 2.0 virginica 3
148 6.2 3.4 5.4 2.3 virginica 3
149 5.9 3.0 5.1 1.8 virginica 3

150 rows × 6 columns

con lo cual hemos conseguido nuestro objetivo.

Podemos reemplazar los valores de más de una columna a la vez, por ejemplo

In [20]:
dict_reemplazo = {'species_num': dict_valor,
                  'species': dict_valor}
# pasamos el diccionario anterior al metodo replace()
df.replace(dict_reemplazo)
Out[20]:
sepal_length sepal_width petal_length petal_width species species_num
0 5.1 3.5 1.4 0.2 1 1
1 4.9 3.0 1.4 0.2 1 1
2 4.7 3.2 1.3 0.2 1 1
3 4.6 3.1 1.5 0.2 1 1
4 5.0 3.6 1.4 0.2 1 1
... ... ... ... ... ... ...
145 6.7 3.0 5.2 2.3 3 3
146 6.3 2.5 5.0 1.9 3 3
147 6.5 3.0 5.2 2.0 3 3
148 6.2 3.4 5.4 2.3 3 3
149 5.9 3.0 5.1 1.8 3 3

150 rows × 6 columns

donde ahora modificamos los valores de dos columna. Asimismo, podríamos pasar diferentes diccionarios de reemplazo como el diccionario dict_valor.

Elementos importantes¶

Dentro de un dataframe podemos obtener cierta información de nuestros datos. Por ejemplo, podemos ver el tipo de dato de las columnas, si hay en ellas valores nulos, el total de filas y el peso del conjunto de datos:

In [116]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 6 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   sepal_length  150 non-null    float64
 1   sepal_width   150 non-null    float64
 2   petal_length  150 non-null    float64
 3   petal_width   150 non-null    float64
 4   species       150 non-null    object 
 5   species_num   150 non-null    int64  
dtypes: float64(4), int64(1), object(1)
memory usage: 7.2+ KB

donde vemos que el conjunto de datos tiene un peso de aproximadamente 7.2 kilobytes. Mencionamos que el tipo de dato object de pandas es el equivalente al tipo de datos string normal de python.

Podemos ver un resumen de estadísticas:

In [117]:
df.describe()
Out[117]:
sepal_length sepal_width petal_length petal_width species_num
count 150.000000 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000 1.199333 2.000000
std 0.828066 0.435866 1.765298 0.762238 0.819232
min 4.300000 2.000000 1.000000 0.100000 1.000000
25% 5.100000 2.800000 1.600000 0.300000 1.000000
50% 5.800000 3.000000 4.350000 1.300000 2.000000
75% 6.400000 3.300000 5.100000 1.800000 3.000000
max 7.900000 4.400000 6.900000 2.500000 3.000000

que nos indica:

  • count: número de elementos totales (número de filas)
  • mean: promedio de los valores en esa columna
  • std: desviación estándar en esa columna (básicamente qué tanto nos alejamos del promedio)
  • min: valor mínimo en esa columna
  • man: valor máximo en esa columna

Podemos ver, en cuanto a columna numéricas, el coeficiente de correlación de pearson (el cual nos dice si una variable y otra presentar alguna relación lineal):

In [118]:
df.corr(method='pearson')
Out[118]:
sepal_length sepal_width petal_length petal_width species_num
sepal_length 1.000000 -0.117570 0.871754 0.817941 0.782561
sepal_width -0.117570 1.000000 -0.428440 -0.366126 -0.426658
petal_length 0.871754 -0.428440 1.000000 0.962865 0.949035
petal_width 0.817941 -0.366126 0.962865 1.000000 0.956547
species_num 0.782561 -0.426658 0.949035 0.956547 1.000000

donde:

  • valores cercanos a uno nos indica que existe una relación lineal entre los datos, o que, básicamente, dichas variables están relacionadas de manera proporcional
  • valores cercanos a menos uno nos indica que existe una relación lineal entre los datos, o que, básicamente, dichas variables están relacionadas de manera inversamente proporcional
  • valores cercanos a cero nos indican que no hay relación lineal.

Del ejemplo anterior tenemos que las variables species_num (la cual representan a las especies) está altamente relacionada con la variable petal_width.

¿Qué otras relaciones, a parte de las que mencionamos inmediatamente antes, pueden detectarse a partir de la tabla de correlaciones?

Graficación con pandas ¶

Pandas tiene métodos incorporados que permiten la realización de diversos gráficos.

Diagramas de dispersión¶

Podemos realizar un gráfico de dispersión entre dos variables (columnas) de un dataframe utilizando plot.scatter() que pandas tiene incorporado. Por ejemplo crearemos el diagrama de dispersión entre las columnas del largo del sépalo versus el ancho del sépalo:

In [43]:
df.plot.scatter(x='sepal_length', y='sepal_width', c='red')
Out[43]:
<AxesSubplot:xlabel='sepal_length', ylabel='sepal_width'>

Podemos colorear los puntos del diagrama de dispersión de acuerdo a la especie, para ello utilizaremos al columna species_num y reemplazaremos los valores 1,2 y 3 por códigos hexagécimales de tres diferentes colores:

In [31]:
dict_colores = {1: '#FF0000', 2: '#FF7F00', 3: '#FDDE0E'}
df = df.replace({'species_num': dict_colores})
In [33]:
df.head()
Out[33]:
sepal_length sepal_width petal_length petal_width species species_num
0 5.1 3.5 1.4 0.2 setosa #FF0000
1 4.9 3.0 1.4 0.2 setosa #FF0000
2 4.7 3.2 1.3 0.2 setosa #FF0000
3 4.6 3.1 1.5 0.2 setosa #FF0000
4 5.0 3.6 1.4 0.2 setosa #FF0000
In [42]:
# para el parametro c colocamos el nombre de la columna species_num
# el cual ahora tiene como entradas los codigos hexagecimales
# de tres diferentes colores
df.plot.scatter(x='sepal_length', y='sepal_width', c='species_num')
Out[42]:
<AxesSubplot:xlabel='sepal_length', ylabel='sepal_width'>

Podemos aumentar el tamaño de los puntos mediante el parámetro s:

In [50]:
ax = df.plot.scatter(x='sepal_length', y='sepal_width', c='species_num', s=50)

Histogramas¶

Un histograma es un gráfico que se utiliza para representar la distribución de frecuencias, lo cual nos puede servir para observar la distribución de una variable. Asimismo, un histograma nos puede servir para observar la frecuencia de aparición de ciertas clases.

Por ejemplo, podemos ver la frecuencia de aparición de cada especie:

In [107]:
# volveremos a tener la siguiente estructura en el dataframe:
# cargamos de nuevo los datos
df = sns.load_dataset("iris")
# diccionario para cambiar valores
dict_valor = {'setosa': 1, 'versicolor': 2, 'virginica': 3}
# agregamos una columna nueva
df['species_num'] = df.species
# cambiamos los valores de la columna anterior
df = df.replace({'species_num': dict_valor})
df.head()
Out[107]:
sepal_length sepal_width petal_length petal_width species species_num
0 5.1 3.5 1.4 0.2 setosa 1
1 4.9 3.0 1.4 0.2 setosa 1
2 4.7 3.2 1.3 0.2 setosa 1
3 4.6 3.1 1.5 0.2 setosa 1
4 5.0 3.6 1.4 0.2 setosa 1

Para graficar un histograma deberemos de escribrir

<nombre_dataframe>.<nombre_columna_interes>.hist()

de modo que

In [91]:
ax = df.species_num.plot.hist()

lo cual nos dice, como sabíamos antes, que hay 50 elementos por especie. Es preciso mencionar que la variable o columna de la cual queremos graficar el histograma debe ser numérica.

Podemos graficar los siguientes histogramas:

In [92]:
# histogramas de frecuencia de la variable sepal_length
ax = df.sepal_length.plot.hist(bins = 20, grid=True, figsize=(10,4))

donde configuramos 20 rectángulos (bins=20), mostramos la cuadrícula (grid=True) y configuramos el tamaño del gráfico.

Podemos cambiar el color del histograma

In [100]:
# histogramas de frecuencia de la variable petal_length
ax = df.petal_length.plot.hist(bins = 20, grid=True, figsize=(10,4), color='red')
In [105]:
# histogramas de frecuencia de la variable petal_width
ax = df.petal_width.plot.hist(bins = 20, grid=True, figsize=(10,4), 
                              color='#FF7F00')