Data-Wrangling ES
Data-Wrangling ES
<a href="[Link]
<img src="[Link]
</a>
Análisis de Datos con Python
Data Wrangling
¡Bienvenido!
Al terminar este cuaderno habrás aprendido los conceptos básicos sobre Data Wrangling
Indice
Identificar y manejar valores faltantes
Identificar valores faltantes
Manejar valores faltantes
Corregir el formato de los datos
</li>
<li><a href="#data_standardization">Estandarización de los Datos</a></li>
<li><a href="#data_normalization">Normalización de los Datos (centrado/escalado)</a></li>
<li><a href="#binning">Discretización</a></li>
<li><a href="#indicator">Variable Indicadora</a></li>
Tiempo Estimado: 30 min
¿Cual es la función del Data Wrangling?
Data Wrangling es el proceso de convertir los datos desde un formato inicial a uno apropiado para
su análisis.
Cual es el ritmo de consumo de combustible (L/100k) de un automovil de diesel?
Importar Datos
Puedes encontrar el “Conjunto de Datos Automotriz” en el siguiente enlace:
[Link] Usaremos
estos datos a lo largo de este curso.
Importar pandas
[1]: import pandas as pd
import [Link] as plt
1
Leer los datos desde la URL y añadir los encabezados relacionados.
URL del conjunto de datos
Este conjunto de datos esta ubicado en un objeto IBM Cloud haz clic AQUI para tener almace-
namiento gratuito.
[2]: filename = "[Link]
,→CognitiveClass/DA0101EN/[Link]"
"drive-wheels","engine-location","wheel-base",␣
,→"length","width","height","curb-weight","engine-type",
"num-of-cylinders",␣
,→"engine-size","fuel-system","bore","stroke","compression-ratio","horsepower",
"peak-rpm","city-mpg","highway-mpg","price"]
Utiliza el método de Pandas read_csv() para cargar los datos desde la dirección web. Establece el
parámetro “names” igual al de la lista “headers” de Python.
[4]: df = pd.read_csv(filename, names = headers)
Utiliza el método head() para mostrar las primeras cinco filas del dataframe.
2
4 mpfi 3.19 3.40 8.0 115 5500 18
highway-mpg price
0 27 13495
1 27 16500
2 26 16500
3 30 13950
4 22 17450
[5 rows x 26 columns]
Como se puede ver, algunos signos de interrogación aparecen en el dataframe; estos son valores
faltantes que pueden dificultar nuestro futuro análisis.
¿Como identificamos y manejamos todos aquellos valores que faltan?
¿Como trabajar con valores faltantes?
Pasos para trabajar con valores faltantes:
identificar los datos faltantes
manejar los datos faltantes
corregir el formato de los datos
Identificar y manejar valores faltantes
Identificar valores faltantes
Convertir “?” a NaN
En el conjunto de datos del automovil, los datos que faltan aparecen con el signo “?”. Cambiamos
“?” por NaN (Not a Numer) el cual es el marcador por defecto de Python para valores faltantes
por razones de conveniencia y velocidad de computo. Aqui usamos la función:
para reemplazar A por B
[6]: import numpy as np
3
1 convertible rwd front 88.6 … 130
2 hatchback rwd front 94.5 … 152
3 sedan fwd front 99.8 … 109
4 sedan 4wd front 99.4 … 136
highway-mpg price
0 27 13495
1 27 16500
2 26 16500
3 30 13950
4 22 17450
[5 rows x 26 columns]
dentify_missing_values
Evaluar Valores Faltantes
Los valores que faltan son convertidos al estandar de Python. Usamos las funciones pre establecidas
de Python para identificar estos valores. Existen dos métodos para detectar los datos faltantes.
.isnull()
.notnull()
El valor de salida es del tipo booleano e indica si el valor pasado como argumento es en verdad
alguno de los que faltan.
[7]: missing_data = [Link]()
missing_data.head(5)
4
4 False False False False … False
[5 rows x 26 columns]
symboling
False 205
Name: symboling, dtype: int64
normalized-losses
False 164
True 41
Name: normalized-losses, dtype: int64
make
False 205
Name: make, dtype: int64
fuel-type
False 205
Name: fuel-type, dtype: int64
5
aspiration
False 205
Name: aspiration, dtype: int64
num-of-doors
False 203
True 2
Name: num-of-doors, dtype: int64
body-style
False 205
Name: body-style, dtype: int64
drive-wheels
False 205
Name: drive-wheels, dtype: int64
engine-location
False 205
Name: engine-location, dtype: int64
wheel-base
False 205
Name: wheel-base, dtype: int64
length
False 205
Name: length, dtype: int64
width
False 205
Name: width, dtype: int64
height
False 205
Name: height, dtype: int64
curb-weight
False 205
Name: curb-weight, dtype: int64
engine-type
False 205
Name: engine-type, dtype: int64
num-of-cylinders
False 205
Name: num-of-cylinders, dtype: int64
6
engine-size
False 205
Name: engine-size, dtype: int64
fuel-system
False 205
Name: fuel-system, dtype: int64
bore
False 201
True 4
Name: bore, dtype: int64
stroke
False 201
True 4
Name: stroke, dtype: int64
compression-ratio
False 205
Name: compression-ratio, dtype: int64
horsepower
False 203
True 2
Name: horsepower, dtype: int64
peak-rpm
False 203
True 2
Name: peak-rpm, dtype: int64
city-mpg
False 205
Name: city-mpg, dtype: int64
highway-mpg
False 205
Name: highway-mpg, dtype: int64
price
False 201
True 4
Name: price, dtype: int64
Con base en el resumén de arriba, cada columna tiene 205 filas de datos, siete columnas que
7
contienen información faltante:
“normalized-losses”: 41 datos faltantes
“num-of-doors”: 2 datos faltantes
“bore”: 4 datos faltantes
“stroke” : 4 datos faltantes
“horsepower”: 2 datos faltantes
“peak-rpm”: 2 datos faltantes
“price”: 4 datos faltantes
Manejar Valores Faltantes
¿Como se manejan los valores faltantes?
eliminando datos a. eliminar toda la fila b. eliminar toda la columna
remplazando datos a. remplazarlos por la media b. remplazarlos por la frecuencia c. remplazarlos
en base a otras funciones
Todas las columnas deberían ser eliminadas solo si la mayoría de las entradas de la columna estan
vacias. En nuestro conjunto de datos ninguna de las columnas estan tan vacias como para elim-
inarlas completamente. Tenemos cierta libertad de elegir cual método usar para reemplazar los
datos; sin embargo, algunos métodos puedieran ser mejores que otros. Se aplicara cada método
para muchas columnas distintas:
Remplazar con la Media:
“normalized-losses”: 41 datos faltantes , remplazar con la media
“stroke”: 4 datos faltantes , remplazar con la media
“bore”: 4 datos faltantes , remplazar con la media
“horsepower”: 2 datos faltantes , remplazar con la media
“peak-rpm”: 2 datos faltantes , remplazar con la media
Remplazar con la Frecuancia:
“num-of-doors”: 2 datos faltantes, remplazar con “cuatro”.
Razón: El 84% de los sedanes es de cuatro puertas. Debido que tener cuatro puertas es mas
frecuente, es mas probable que ocurra
</li>
Eliminar toda la fila:
“price”: 4 datos faltantes, simplemente se borra toda la columna.
Razón: El precio es lo que queremos predecir. Cualquier dato de entrada sin precio no puede ser
usado para predecir; debido a esto toda fila sin información del precio no es de utilidad
</li>
8
Calcular el promedio de la columna
[9]: avg_norm_loss = df["normalized-losses"].astype("float").mean(axis=0)
print("Average of normalized-losses:", avg_norm_loss)
Pregunta #1:
De acuerdo al ejemplo de arriba, remplaza NaN en la collumna “stroke” por la media.
[13]: # Escribe tu código aquí y presiona Shift+Enter para ejecutar
# calculate the mean vaule for "stroke" column
avg_stroke = df["stroke"].astype("float").mean(axis = 0)
print("Average of stroke:", avg_stroke)
9
Average peak rpm: 5125.369458128079
Remplaza “NaN” por el valor de la media:
[17]: df['peak-rpm'].replace([Link], avg_peakrpm, inplace=True)
Para ver los valores presentes en una columna podemos usar el método “.value_counts()”:
[18]: df['num-of-doors'].value_counts()
Podemos ver que el tipo mas común es el de cuatro puertas. Además podemos usar el método
.idxmax()” para calcular automaticamente el tipo mas comun:
[19]: df['num-of-doors'].value_counts().idxmax()
[19]: 'four'
[22]: [Link]()
10
fuel-system bore stroke compression-ratio horsepower peak-rpm city-mpg \
0 mpfi 3.47 2.68 9.0 111 5000 21
1 mpfi 3.47 2.68 9.0 111 5000 21
2 mpfi 2.68 3.47 9.0 154 5000 19
3 mpfi 3.19 3.40 10.0 102 5500 24
4 mpfi 3.19 3.40 8.0 115 5500 18
highway-mpg price
0 27 13495
1 27 16500
2 26 16500
3 30 13950
4 22 17450
[5 rows x 26 columns]
11
num-of-cylinders object
engine-size int64
fuel-system object
bore object
stroke object
compression-ratio float64
horsepower object
peak-rpm object
city-mpg int64
highway-mpg int64
price object
dtype: object
Como podemos ver arriba, algunas columnas no tienen el tipo correcto de dato. Las variables
numericas deben ser de tipo ‘float’ o ‘int’, y las variables con cadenas como pueden ser las categorias
deben ser de tipo ‘object’. Por ejemplo, las variables ‘bore’ y ‘stroke’ son valores numericos que
describen los motores, asi que podemos esperar que sean del tipo ‘float’ o ‘int’; sin embargo, se
muestran como tipo ‘objetc’. Debemos convertir los tipos de datos al formato apropiado para cada
columna utilizando el método “astype()”.
Convertir el tipo de datos al formato apropiado
[24]: df[["bore", "stroke"]] = df[["bore", "stroke"]].astype("float")
df[["normalized-losses"]] = df[["normalized-losses"]].astype("int")
df[["price"]] = df[["price"]].astype("float")
df[["peak-rpm"]] = df[["peak-rpm"]].astype("float")
12
fuel-system object
bore float64
stroke float64
compression-ratio float64
horsepower object
peak-rpm float64
city-mpg int64
highway-mpg int64
price float64
dtype: object
¡Perfecto!
Ahora, finalmente obtenemos el conjunto de datos limpio, sin valores faltantes y en un formato
correcto.
Estandarización de los Datos
Los datos normalmente se colectan desde distintas agencias con formatos distintos. (La es-
tandarización de datos es también un termino para un tipo particular de normalización donde
restamos la media y la dividimos por la desviación estandar).
¿Qué es la estandarización?
La estandarización es el proceso de transformar datos en un formato común que permita al inves-
tigador realizar comparaciones significativas.
Ejemplo
Convertir m.p.g (millas por galón) a L/100km:
En nuestro conjunto de datos, las columnas de consumo de combustible “city-mpg” y “highway-
mpg” estan representadas por m.p.g. (millas por galón). Deberás asumir que estamos desarrollando
una aplicación en un país que acepte el estandar de consumo en L/100km.
¿Es necesario transformar los datos para convertir m.p.g. en L/100km?
La formula de conversión es
L/100km = 235 / m.p.g.
Podemos realizar muchas operaciones matematicas directamente en Pandas.
[26]: [Link]()
13
0 two convertible rwd front 88.6 …
1 two convertible rwd front 88.6 …
2 two hatchback rwd front 94.5 …
3 four sedan fwd front 99.8 …
4 four sedan 4wd front 99.4 …
[5 rows x 26 columns]
[27]: # Convertir m.p.g. a L/100km mediante una operación matematica (235 dividido␣
,→por m.p.g.)
df['city-L/100km'] = 235/df["city-mpg"]
14
3 mpfi 3.19 3.40 10.0 102 5500.0 24
4 mpfi 3.19 3.40 8.0 115 5500.0 18
[5 rows x 27 columns]
Pregunta #2:
De acuerdo al ejemplo de arriba, convierte m.p.g. a L/100km en la columna “highway-mpg” y
cambia el nombre de la columna a “highway-L/100km”.
15
highway-mpg price city-L/100km
0 8.703704 13495.0 11.190476
1 8.703704 16500.0 11.190476
2 9.038462 16500.0 12.368421
3 7.833333 13950.0 9.791667
4 10.681818 17450.0 13.055556
[5 rows x 27 columns]
Pregunta #3:
De acuerdo al ejemplo anterior, normaliza la columna “height”.
[31]: # Escribe tu código aquí y presiona Shift+Enter para ejecutar
df['height'] = df['height']/df['height'].max()
# show the scaled columns
df[["length","width","height"]].head()
16
¿Qué es la discretización?
Discretizar es el proceso de transformar variables numericas continuas en ‘contenedores’ discretos
para el análisis agrupado.
Ejemplo:
En nuestro conjunto de datos, “horsepower” es una variable con valor en el rango de 48 a 288,
tiene 57 valores únicos. ¿Qué pasaría si solo nos ocuparamos de las diferencias de precio entre
automoviles con altos, medios y pocos caballos de fuerza (3 tipos)? ¿Podriamos reacomodarlos
dentro de tres ‘contenedores’ para facilitar el análisis?
Usaremos el método de Pandas ‘cut’ para segmentar la columna ‘horsepower’ en 3 contenedores.
Ejemplo de discretización de datos con Pandas
Corregir el formato de los datos
[32]: df["horsepower"]=df["horsepower"].astype(int, copy=True)
17
Quisieramos 3 contenedores de igual tamaño para poder utilizar la función linspace(start_value,
end_value, numbers_generated de numpy.
Debido a que queremos incluir el valor mínimo de caballos de fuerza que queremos establecer
start_value=min(df[“horsepower”]).
Debido a que queremos incluir el valor máximo de caballos de fuerza que queremos establecer
end_value=max(df[“horsepower”]).
Debido a que estamos construyendo 3 contenedores de igual longitud debe haber 4 divisores, asi
que numbers_generated=4.
Construimos un arreglo tipo contenedor, desde un valor mínimo al máximo y un ancho de bando
calculado arriba. Los contenedores seran valores usados para determinar cuando uno de ellos
termina y otro comienza.
[34]: bins = [Link](min(df["horsepower"]), max(df["horsepower"]), 4)
bins
Aplicamos la función “cut” para determinar a quien pertenece cada valor de “df[‘horsepower’]”.
18
[36]: df['horsepower-binned'] = [Link](df['horsepower'], bins, labels=group_names,␣
,→include_lowest=True )
df[['horsepower','horsepower-binned']].head(20)
19
Revisa el dataframe de arriba con cuidado y encontrarás que la última columna da a los contenedores
para “horsepower” 3 categorias ((“Low”,“Medium” and “High”).
Hemos reducido exitosamente el número de intervalos de 57 a 3.
Visualización de Contenedores
Normalmente un histograma se utiliza para visualizar la distribución de los contenedores creados
arriba.
[39]: %matplotlib inline
import matplotlib as plt
from matplotlib import pyplot
a = (0,1,2)
20
The plot above shows the binning result for attribute “horsepower”.
Variable Indicadora (o variable tonta)
¿Qué es una variable indicadora?
Es una variable numerica usada para etiquetar categorías. Son llamadas “tonta” porque los números
en ellas no tienen ningun significado.
¿Para que se usa una variable indicadora?
Para poder usar variables para el analisis de regresión en los módulos posteriores.
Ejemplo
Vemos que la columna “fuel-type” tiene dos valores únicos, “gas” o “diesel”. La regresión no entiende
palabras, solo números. Para usar este atributo en el análisis de regresión debemos convertir “fuel-
type” en una variable indicadora.
Usaremos el método Pandas ‘get_dummies’ para asignarle un valores numericos a difentes catego-
rias de tipo de combustible.
[40]: [Link]
21
'compression-ratio', 'horsepower', 'peak-rpm', 'city-mpg',
'highway-mpg', 'price', 'city-L/100km', 'horsepower-binned'],
dtype='object')
dummy_variable_1.head()
Ahora tenemos el valor 0 para representar “gas” y 1 para “diesel” en la columna “fuel-type”.
Insertaremos esta columna en el nuestro dataset original.
[43]: # combinar el dataframe "df" y "dummy_variable_1"
df = [Link]([df, dummy_variable_1], axis=1)
[44]: [Link]()
22
0 convertible rwd front 88.6 0.811148 …
1 convertible rwd front 88.6 0.811148 …
2 hatchback rwd front 94.5 0.822681 …
3 sedan fwd front 99.8 0.848630 …
4 sedan 4wd front 99.4 0.848630 …
[5 rows x 29 columns]
Las últimas dos columnas ahora son las representación de la variable indicadora del tipo de com-
bustible. Ahora es unos y ceros.
Pregunta #4:
Al igual que arriba, crear una variable indicadora de “aspiration”: “std” a 0, mientras “turbo” a 1.
[46]: # Escribe tu código aquí y presiona Shift+Enter para ejecutar
# get indicator variables of aspiration and assign it to data frame␣
,→"dummy_variable_2"
dummy_variable_2 = pd.get_dummies(df['aspiration'])
23
Pregunta #5:
Combinar el nuevo dataframe con el original y despues elimina la columna ‘aspiration’
[47]: # Escribe tu código aquí y presiona Shift+Enter para ejecutar
#merge the new dataframe to the original datafram
df = [Link]([df, dummy_variable_2], axis=1)
[49]: "'df.to_csv('clean_df.csv')"
filepath = "[Link]"
word_count = 0
for cell in [Link][0].cells:
if cell.cell_type == "markdown":
word_count += len(cell['source'].replace('#', '').lstrip().split(' '))
print(word_count)"""
24
nb = [Link](f, \'json\')\n\nword_count = 0\nfor cell in
[Link][0].cells:\n if cell.cell_type == "markdown":\n
word_count += len(cell[\'source\'].replace(\'#\', \'\').lstrip().split(\'
\'))\nprint(word_count)'
[ ]:
25