Naps Tecnología y educación

Fases del análisis de datos usando Python

Veremos las siguientes fases del análisis de datos: ingesta de datos, diagnóstico de la calidad de los datos, y agrupación de variables.

Si deseas obtener el conjunto de datos que vamos a utilizar, puedes descargarlo aquí: vehiculos_original.csv (tamaño 4.3 MB).

Los datos fueron tomados de https://www.fueleconomy.gov/feg/ws/index.shtml

Aprende las primeras fases del análisis de datos en Python

Primeras fases del análisis de datos

Fase 1. Ingesta de datos.

En esta fase leemos el conjunto de datos original y le aplicamos el tratamiento necesario para facilitar su uso, por ejemplo, renombrar las columnas.

Importar pandas y leer el archivo csv

import pandas as pd
vehiculos = pd.read_csv("vehiculos_original.csv")

Renombrar las columnas

vehiculos = vehiculos.rename(columns={
	"cylinders": "cilindros",
	"trany": "transmision",
	"make": "fabricante",
	"model": "modelo",
	"displ": "desplazamiento",
	"drive": "traccion",
	"VClass": "clase",
	"fuelType": "combustible",
	"comb08": "consumo",
	"co2TailpipeGpm": "co2"
	})

Guardar los cambios en un nuevo csv para no modificar el archivo original

vehiculos.to_csv("vehiculos_paso1.csv", index=False)

Fase 2. Diagnóstico de la calidad de los datos (QA)

En esta fase revisamos que no existan datos duplicados (que no debiesen estar duplicados), datos nulos o inexistentes (que pudiesen arrojarnos errores de procesamiento), y se revisan también los valores extremos.

Importamos las librerías que requeriremos, leemos el archivo csv y mostramos cuántas filas y columnas tiene nuestro dataset.

import pandas as pd
import matplotlib.pyplot as plt
vehiculos = pd.read_csv("vehiculospaso1.csv")
print(vehiculos.shape)

Eliminación de filas duplicadas

Veamos cuántas filas duplicadas hay

print (vehiculos[vehiculos.duplicated()].shape)

Eliminamos las filas duplicadas

vehiculos = vehiculos.drop_duplicates()
print (vehiculos.shape)

Cardinalidad

Midamos ahora la cardinalidad de algunas columnas. Con esto queremos observar si una cantidad grande de registros tiene el mismo valor.

La siguiente función nos permite ver el porcentaje de valores comunes en cada columna.

n_registros = len(vehiculos)
def valores_duplicados_col(df):
	for columna in df:
		n_por_valor = df[columna].value_counts()
		mas_comun = n_por_valor.iloc[0]
		menos_comun = n_por_valor.iloc[-1]
		print ("{} | {} - {} | {}".format(
			df[columna].name,
			round(mas_comun/(1.0*n_registros),3),
			round(menos_comun/(1.0*n_registros),3),
			df[columna].dtype
		))
print("Revisando valores duplicados")
valores_duplicados_col(vehiculos)

Desde luego podemos observar ésto en forma gráfica, columna por columna. Por ejemplo, para las columnas “transmision” y “combustible”:

vehiculos.transmision.value_counts(normalize=True).plot.barh()
vehiculos.cilindros.hist()
vehiculos.combustible.value_counts(normalize=True).plot.barh()
plt.show()

Revisión de valores inexistentes

La siguiente función nos permite observar el porcentaje de valores inexistentes en cada columna

print ("Revisando valores inexistentes")
n_registros = len(vehiculos)
def valores_inexistentes_col(df):
	for columna in df:
		print ("{} | {} |{}".format(
			df[columna].name, 
			len(df[df[columna].isnull()]) / (1.0*n_registros),
			df[columna].dtype


			))

valores_inexistentes_col(vehiculos)

Valores extremos

Se consideran valores extremos aquellos cuya puntuación Z es mayor a 3. Se considera a Z como

Z = (x – media ) / desviación_estándar

Afortunadamente, contamos con la librería scipy que nos permite obtener la puntación Z fácilmente.

Podemos implementar una función que nos permita observar la cantidad de valores extremos que existen en cada columna.

from scipy import stats
import numpy as np 


def extermos_col(df):
	for columna in df:
		if df[columna].dtype != np.object:
			n_extremos = len(df[np.abs(stats.zscore(df[columna]))>3])
			print ("{} | {} | {}".format(
				df[columna].name,
				n_extremos,
				df[columna].dtype

				))

print ("Revisando valores extremos")
extermos_col(vehiculos)

Gráficamente también podemos revisar los valores extremos. Por ejemplo, en las columnas consumo y co2.

vehiculos.boxplot(column='consumo')
vehiculos.boxplot(column='co2')
plt.show()

Se observa que hay coches que no producen co2. ¿Qué combustible usarán?

print(vehiculos[vehiculos.co2==0].combustible.unique())
#Los tipos de combustible son
print(vehiculos.combustible.unique())

Bueno, para éste ejercicio sólo nos interesan los vehículos que sí generan co2, por lo que vamos a eliminar a los que no generan co2.

print (vehiculos[vehiculos.co2==0].shape) #Hay 139 que no generan co2
vehiculos_no_electricos = vehiculos[vehiculos.co2>0] 
print (vehiculos_no_electricos.shape)

Conclusiones de ésta fase

Hay 1506 registros duplicados que se han eliminado.
Las variables desplazamiento, cilindro, transmision y traccion tienen valores nulos o inexistentes.
La variable combustible tiene una clase dominante en 65%.
Se eliminaron 139 registros correspondientes a autos electricos que no emiten co2.

Guardamos un nuevo csv con los cambios

vehiculos_no_electricos.to_csv("vehiculospaso2.csv", index=False)

Fase 3. Agrupación de variables

Se requiere agrupar algunas variables a fin de reducir el campo de estudio a aquellas variables que nos interesan.

La siguiente función permite ver los valores únicos de cada columna.

vehiculos = pd.read_csv("vehiculospaso2.csv")

def valores_unicos_col(df):
	for column in df:
		print ("{} | {} | {} ".format(
			df[column].name, len(df[column].unique()), df[column].dtype
			))
print ("=== Valores unicos por columna")
valores_unicos_col(vehiculos)

Agrupación de variables categóricas: Primer caso, la columna “clase”

Veamos qué valores componen la columna clase

print ("*** Valores de la columna clase")
print (vehiculos.clase.unique())

Si se observan, podemos clasificar todos éstos valores en ciertas categorías. Vamos a crear las siguientes categorías o tipos para la columna clase: Coches pequeños, Coches medianos, Coches grandes, Camionetas, Vehículos especiales, Deportivos, Coche familiar, Furgoneta.

A continuación creamos una nueva columna llamada “clase_tipo”, donde se clasificará cada registro en su tipo correspondiente.

pequeno = ['Compact Cars', 'Subcompact Cars', 'Two Seaters', 'Minicompact Cars']
medio = ['Midsize Cars']
grande= ['Large Cars']

vehiculos.loc[vehiculos['clase'].isin(pequeno),'clase_tipo'] = 'Coches pequeños'
vehiculos.loc[vehiculos['clase'].isin(medio),'clase_tipo'] = 'Coches medianos'

vehiculos.loc[vehiculos['clase'].isin(grande),'clase_tipo'] = 'Coches grandes'

vehiculos.loc[vehiculos['clase'].str.contains('Truck'), 'clase_tipo'] = 'Camionetas'
vehiculos.loc[vehiculos['clase'].str.contains('Special Purpose'), 'clase_tipo'] = 'Vehiculos especiales'
vehiculos.loc[vehiculos['clase'].str.contains('Sport Utility'), 'clase_tipo'] = 'Deportivos'
vehiculos.loc[vehiculos['clase'].str.contains('Station'), 'clase_tipo'] = 'Coche familiar'
vehiculos.loc[vehiculos['clase'].str.lower().str.contains('van'), 'clase_tipo'] = 'Furgoneta'

Es útil que las columnas categóricas sean consideradas como tales por Python. A continuación haremos eso a la columna “clase_tipo”.

vehiculos.clase_tipo = vehiculos.clase_tipo.astype("category")

Si deseamos verificar que todas las filas hayan recibido una categoría, podemos contar cuántos registros contiene cada una de ellas.

print ("==== Mis Categorias de clase")
print(vehiculos.clase_tipo.value_counts())

Segundo caso: la columna “traccion”

Agruparemos los registros en dos tipos: dos y cuatro ruedas.

print ("Valores de la columna traccion")
print(vehiculos.traccion.unique())


vehiculos["traccion_tipo"] = "dos"
vehiculos.loc[vehiculos.traccion.isin([
	"4-Wheel or All-Whell Drive", "All-Whell Drive", 
	"4-Wheel Drive", "Part Time 4-Whell Drive"]), "traccion_tipo"] = "cuatro"
print("")
print ("=== Mis Categorias de traccion")
print (vehiculos.traccion_tipo.value_counts())

Tercer caso: la columna “transmision”

Aquí necesitamos solo dos categorías (Manual y Automática) de todas las que el dataset maneja.

vehiculos["transmision_tipo"] = "Automática"
vehiculos.loc[vehiculos.transmision.notnull() & vehiculos.transmision.str.startswith('M'), "transmision_tipo"] = "Manual"

print("")
print ("=== Mis Categorias de transmision")
print (vehiculos.transmision_tipo.value_counts())

Cuarto caso: la columna “combustible”

Crearemos los tipos: Normal, Premium, Hibrido y Otros tipos de combustible

vehiculos["combustible_tipo"] = "Otros tipos de combustible"
vehiculos.loc[vehiculos["combustible"] == "Regular", "combustible_tipo"] = "Normal"
vehiculos.loc[vehiculos["combustible"] == "Premium", "combustible_tipo"] = "Premium"
vehiculos.loc[vehiculos["combustible"].str.contains("Electricity"), "combustible_tipo"]= "Hibrido"

print("")
print ("=== Mis Categorias de combustible")
print (vehiculos.combustible_tipo.value_counts())

Agrupamiento de variables continuas

Las variables continuas tienen valores numéricos por lo que se deben clasificar de acuerdo a rangos de valores.

Esto ocurre en el caso de las columnas “desplazamiento”, “consumo” y “co2”. Éstas columnas las clasificaremos en categorías como “muy bajo”, “bajo”, “moderado”, “alto”, “muy alto”, o de una forma similar.

tipos_tam_motor = ["muy pequeño", "pequeño", "mediano", "grande", "muy grande"]
vehiculos["tamano_motor_tipo"] = pd.qcut(vehiculos["desplazamiento"], 5, tipos_tam_motor) 

print("")
print ("=== Mis Categorias de desplazamiento")
print (vehiculos.tamano_motor_tipo.value_counts())

tipos_consumo = ["muy bajo", "bajo", "moderado","alto", "muy alto"]
vehiculos["consumo_tipo"] = pd.qcut(vehiculos["consumo"], 5, tipos_consumo)

print("")
print ("=== Mis Categorias de consumo")
print (vehiculos.consumo_tipo.value_counts())

tipos_co2 = ["muy bajo", "bajo", "moderado","alto", "muy alto"]
vehiculos["co2_tipo"] = pd.qcut(vehiculos["co2"], 5, tipos_co2)

print("")
print ("=== Mis Categorias de co2")
print (vehiculos.co2_tipo.value_counts())

Por último ajustaremos los valores de consumo y co2 para que ambos utilicen una misma unidad de medida.

litros_por_galon = 3.78541
vehiculos["consumo_litros_milla"] = litros_por_galon / vehiculos.consumo
print(vehiculos.head(5))

vehiculos.plot.scatter(x="consumo_litros_milla", y = "co2")
plt.show()

Guardar los datos en formato pickle

Para evitar que se pierda información sobre qué variables son categóricas, en vez del formato CSV guardaremos en formato pickle. Pandas puede leer y escribir sobre pickle y al hacerlo es como si el dataframe nunca hubiese perdido ninguna propiedad.

vehiculos.to_pickle("vehiculospaso3.pkl")

Éstas son las primeras 3 de las fases del análisis de datos. En otra entrada consideraremos las siguientes.

 

¿Qué te pareció este artículo?
  • No era lo que buscaba ()
  • Regular ()
  • Poco informativo ()
  • Interesante ()
  • Excelente ()
(Visto 2.305 veces)

Tu comentario

opiniones