Justificación y contexto de tu proyecto

1

Proyectos prácticos en ciencia de datos: del aprendizaje a la aplicación

2

Proyectos de Ciencia de Datos: Del Teórico al Práctico Realista

3

Cuándo iniciar un nuevo proyecto de ciencia de datos

4

Herramientas de Comunicación para Proyectos de Ciencia de Datos

5

Compartir Proyectos de Ciencia de Datos: Estrategias y Recursos

6

Comunicación Efectiva en Proyectos de Ciencia de Datos

Quiz: Justificación y contexto de tu proyecto

Ejecutando un proyecto de ciencia de datos

7

Construcción de Proyectos en Ciencia de Datos: Planteamiento de Preguntas

8

Búsqueda y Selección de Conjuntos de Datos Eficientes

9

Análisis de Datos Abiertos para Detectar Anomalías en Compras Públicas

10

Limpieza de Datos: Técnicas y Buenas Prácticas

11

Limpieza de Datos con Python y Pandas para Proyectos de Transparencia

12

Exploración de Datos: Análisis Unidimensional y Bidimensional

13

Análisis y Exploración de Datos con Pandas y Matplotlib

14

Análisis Multidimensional y Visualización de Datos en Python

15

Enriquecimiento de Datos en Ciencia de Datos

16

Enriquecimiento de Datos para Modelos de Machine Learning

17

Modelos de Machine Learning: Supervisado y No Supervisado

18

Modelación de Datos con Aprendizaje Supervisado y No Supervisado

19

Clustering y Detección de Anomalías en Datos de Negocios

20

Detección de Anomalías en Datos Financieros con Modelos Gaussianos

21

Organización y Versionado de Proyectos con Git y Github

22

Publicación de Proyectos en GitHub: Limpieza y Conclusiones

Quiz: Ejecutando un proyecto de ciencia de datos

Comunicando los resultados

23

Cómo Compartir Proyectos de Ciencia de Datos Efectivamente

24

Cómo Escribir un Block Post Técnico Efectivo

25

Presentaciones Efectivas en Comunidades Tecnológicas

26

Optimización de Repositorios en GitHub para Impacto Profesional

27

APIs Restful: Construcción y Despliegue Eficiente

28

Creación de Productos de Datos con Python y Herramientas Visuales

Quiz: Comunicando los resultados

Últimos pasos

29

Cómo y Cuándo Dar Cierre a Proyectos de Ciencia de Datos

30

Recomendaciones para Compartir Proyectos de Datos

31

Presentación y Compartición de Proyectos de Ciencia de Datos

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Limpieza de Datos con Python y Pandas para Proyectos de Transparencia

11/31
Recursos

¿Cómo limpiar datos de un proyecto de transparencia pública?

Enfrentar la limpieza de datos es un paso inevitable y esencial para cualquier profesional de Data Science. Es un desafío constante con el que te cruzarás a lo largo de tu carrera, así que ¡mejor disfrutarlo! En este artículo, trabajaremos con datos provenientes del municipio de Monterrey y utilizaremos herramientas como Python, Pandas y Jupyter Notebook para llevar a cabo este proceso.

¿Cómo comenzamos con la preparación del entorno?

Lo primero es contar con el entorno adecuado para el procesamiento de datos. Aquí tienes algunas opciones:

  • Jupyter Notebook: Ideal si estás usando Anaconda o una instalación estándar de Python.
  • Google Colab: Una excelente alternativa si prefieres trabajar en la nube sin configurar un entorno local.

Después de seleccionar tu entorno, crea una carpeta llamada notebooks y dentro de ella inicia un archivo de texto para registrar las librerías necesarias, facilitando la replicación del proyecto en el futuro.

¿Por qué organizar la información en Pandas?

La organización es clave para mantener un flujo de trabajo ordenado. Iniciamos importando las librerías necesarias:

import pandas as pd
import os

Con Pandas, cargaremos las hojas de cálculo que contienen los datos necesarios. Para ello, utilizamos la función read_excel, especificando las hojas requeridas como “gastos varios”, “servicios profesionales”, “comunicación” y “servicios personales”.

Cada hoja se carga en un DataFrame separado, permitiendo un manejo más controlado de la información:

df_gastos_varios = pd.read_excel('ruta_del_archivo.xlsx', sheet_name='Gastos Varios', skiprows=5)
df_serv_prof = pd.read_excel('ruta_del_archivo.xlsx', sheet_name='Servicios Profesionales', skiprows=5)

¿Cómo simplificar el manejo repetitivo de datos?

Si notas acciones repetitivas durante la carga y el procesamiento de datos, valdría la pena crear funciones para simplificar y automatizar el proceso, aunque inicialmente optamos por manejar cada hoja manualmente por la baja cantidad de observaciones.

¿Cómo concatenamos los datos en un solo lugar?

Una vez que hemos cargado todas las hojas necesarias, es momento de unificarlas en un solo DataFrame:

df_completo = pd.concat([df_gastos_varios, df_serv_prof, df_comunicacion, df_personales], ignore_index=True)

¿Cómo limpiamos datos sucios o innecesarios?

Uno de los principales retos durante la limpieza de datos es identificar las filas innecesarias, como aquellos totales que suelen encontrarse en ciertas hojas de cálculo. Usamos dropna() de Pandas para eliminar filas que contengan datos faltantes:

df_completo = df_completo.dropna(how='any')

Esto reduce el conjunto de datos a las entradas realmente válidas.

¿Cómo verificamos la limpieza de datos y tipos de información?

Verificar que los datos estén con el tipo apropiado es crucial para evitar errores en el análisis:

print(df_completo.dtypes)

Verifica también que los meses correspondan al periodo de estudio para confirmar la calidad de los datos. En este caso, confirmamos que todos los registros pertenecen al mes de diciembre.

¿Cómo almacenamos el conjunto de datos limpio?

Guardamos el conjunto de datos procesado y limpio en un formato legible y común como CSV:

df_completo.to_csv('data_clean_compras.csv', index=False)

Ahora, tu conjunto de datos está listo para análisis futuros. Continúa explorando y modelando la información, abordando cualquier reto que se presente, y comparte tus experiencias con otros aprendices de Data Science. ¡El descubrimiento de conocimientos está a un paso más cerca!

Aportes 21

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Aquí va mi versión de función para crear los distintos dataframes:

def dataframe(file, sheet, rows):
    df=pd.read_excel(file, sheet_name=sheet, skiprows=rows)
    df['SHEET']=sheet
    return df
df_personales=dataframe('12_DICIEMBRE_2020.xlsx', 'SERV. PERS.', 5)
df_personales.head() 

Me tomó un par de días lograrlo (tenía data de gobiernos). Estos fueron algunos retos que tuve y aprendizajes:

  • Fechas: la mayoría de veces hay que pasar del tipo object al tipo datetime. Un reto especial que encontré fue que se debe usar el parámetro dayfirst=True en el método pd.to_datetime() cuando el formato tiene el día primero. Si no se realiza, las fechas se volverán locas y todo saldrá mal (estuve 3 horas trabajando con la data incorrecta). 😂
  • Datos negativos y datos erróneos: una buena práctica si se tiene muchos datos es visualizarlos para ver si todo está bien (tip: usa figsize=[12, 8] o más para que puedas visualizar correctamente y no se te escape nada). Aquí encontré datos que no debían ser negativos como negativos y tuve que transformarlos. Además, encontré datasets que en un solo día tenían la mayoría de registros, así que tuve que buscar otros que tengan la información tomada correctamente.
  • Trasponer: me encontré registros que me hubieran servido mucho como filas, pero estaban como columnas. .transpose() me salvó acá.
  • Crear nuevos datos: había muchas cosas como datos acumulados y datos agrupados que me servirían mucho, no estaban en la data original, pero hice agregaciones y los fui creando para mi análisis futuro.
  • Eliminar columnas: así mismo, muchas columnas no me servirían, así que las eliminé y luego exporté los DataFrames procesados. Funciones como .diff() me ayudaron para agregar con la misma columna pero en diferentes filas.
  • Dividir el trabajo: por último, separé el trabajo en 3 notebooks de limpieza y carga. No sé qué tan buena práctica sea, pero me pareció correcto separarlos por tema (sino hubiera quedado un notebook gigante).

Comparto código que lee y concatena los sheets

import xlrd
import pandas as pd
filename = '12_DICIEMBRE_2020.xlsx'

xls = xlrd.open_workbook(filename, on_demand = True)
sheet_lst = xls.sheet_names()
df = pd.DataFrame()

for i in range(1,len(sheet_lst)):
    df_read = pd.read_excel(filename, sheet_name=sheet_lst[i], skiprows=5)    
    df_read['sheet'] = sheet_lst[i]
    df = df.append(df_read)

Análisis de la Movilidad en Bogotá

¿Cuáles son las rutas más críticas de movilidad y sus características en la ciudad de Bogotá?

Se toman los datos de la plataforma:
https://datos.movilidadbogota.gov.co

He tomado los datasets del año 2019, vienen en archivos CSV para cada mes:

Utilicé la siguiente función para tener un solo DF (para mí fue un reto):

'''
Recibe como parámetro de entrada una lista de archivos CSV,
hace la lectura y concatena los dataframes, siendo esta concatenación el retorno.
Los datos en los archivos CSV deben tener la misma estructura.
'''
def df_builder(data_list):
    n_files = len(data_list) - 1
    df_full = pd.read_csv(data_list[n_files])
    
    for i in range(n_files - 2):
        df_i = pd.read_csv(data_list[i])
        df_full = pd.concat([df_full, df_i])
    
    return df_full

La función toma 1 min y medio aprox en su ejecución, entrega un dataframe de 16.2 M filas x 23 columnas, la cantidad de filas depende del listado de archivos CSV que se tiene.

Realicé una comprobación de la columna AÑO, para asegurar que todos los registros sean del 2019, como sorpresa se encontraron 1072981 veces el año 2020:

Archivo de salida:

Repositorio:
https://github.com/IvanJaimesN/Bogota_Mov

Aquí mi función para reutlizar el código

def create_df(sheet_name, data_path , rows = 5):
    df = pd.read_excel(data_path, sheet_name = sheet_name, skiprows = rows)
    string = sheet_name.replace("  ", "_")
    df["SHEET"] = string
    return df
Creo que el mio fue un poco mas basico pero es lo que me gusta, es con respecto a las ventas en el mercadona de españa, lo cual le añadi la columna ganancia y la columna mes, porque lo que deseo es saber es comparar mes a mes las ventas de estos para poder ver cuanto es el % que va aumentando o disminuyendo y a partir de ello crear planes de accion para las distintas categorias, como tbn me gusta mas el español, puse todas las columnas en español. ```js import pandas as pd df= pd.read_csv('C:/Users/felix/Proyecto/mercadona.csv') # Convertir la columna 'insert_date' en un objeto datetime df['insert_date'] = pd.to_datetime(df['insert_date']) # Crear nuevas columnas para la fecha y la hora df['Fecha'] = df['insert_date'].dt.date df['Hora'] = df['insert_date'].dt.time # Eliminar la columna original 'insert_date' df.drop(columns=['insert_date'], inplace=True) nueva_column = {'id': 'id', 'supermarket': 'Mercado', 'category': 'Categoria', 'name': 'Descripcion', 'price': 'Precio_Costo', 'reference_price': 'Precio_Venta', 'reference_unit': 'Unidad', 'Fecha': 'Fecha', 'Hora': 'Hora'} df = df.rename(columns=nueva_column) # Suponiendo que tienes un DataFrame df y quieres agregar la columna "Ganancia" entre las columnas "Precio Costo" y "Precio Venta" ganancia = df['Precio_Venta'] - df['Precio_Costo'] df.insert(loc=df.columns.get_loc('Unidad'), column='Ganancia', value=ganancia) # Supongamos que tienes un DataFrame df con una columna llamada 'fecha' # Asegúrate de que 'fecha' esté en formato datetime df['Fecha'] = pd.to_datetime(df['Fecha'], format='%d/%m/%Y') # Agregar una nueva columna 'Mes' que contenga el nombre del mes df['Mes'] = df['Fecha'].dt.strftime('%B') df.head() ```import pandas as pd

Para no complicarnos depaso convertir en una funcion el proceso de captura y concatenacion de la informaciond de las hojas de excel

import pandas as pd
import os

##guardamos en un dataframe cada hoja de excel y le agregamos una columna sheets con el nombre de la hola

def concadenar_hojas_en_dataframe(path, hojas, skiprow):
    datas = []
    for hoja in hojas:
        df_data = pd.read_excel(path,sheet_name=hoja,skiprows=skiprow)
        df_data['SHEETS']=hoja
        datas.append(df_data.copy())
    return pd.concat(datas)

##Unimos todas las dataframes

hojas = ['GASTOS VARIOS', 'CONTRATISTAS Y FDO FED', 'SERV PPROF','COMUNICACION','SERV. PERS.']
df_compras_dic = concadenar_hojas_en_dataframe(path='./12_DICIEMBRE_2020.xlsx', hojas=hojas, skiprow=5)

print(df_compras_dic.head(5))
#print(df_compras_dic.tail(5))

print(len(df_compras_dic))
df_compras_dic_com = df_compras_dic.dropna(how='any')
print(len(df_compras_dic_com))
#print(list(df_compras_dic_com['NUM BEN']))

print(df_compras_dic_com.dtypes)
print(df_compras_dic_com['FECHA'].apply(lambda x: x.month).value_counts())

df_compras_dic_com.to_csv('data/clean_compras.csv',index=None) 

Nota: lo estoy trabajando en VScode en mi pc
Tendrian que ajustar los path para trabajar en google colab o jupiter etc etc.

Presente la de problemas al comento de crear el objeto pd, y al final le di solución este es mi código por si presentan inconvenientes:

# Encontramos nuestra ruta
ruta_cuaderno = os.getcwd()

# Realizamos un join con el path que tenemos más el archivo
 ruta_xlsx = os.path.join(ruta_cuaderno, '12_DICIEMBRE_2020.xlsx')

# Confirmamos sí esta excelente sino iteramos hasta dar con la ruta
if os.path.exists(ruta_xlsx):
    print("El archivo existe en la ruta especificada.")
else:
    print("El archivo no existe en la ruta especificada.")

# Ahora lo convertimos a un objeto de pandas
df = pd.read_excel(ruta_xlsx)

# Visualizamos 
df

yo cree una funcion que me devuelva todos los dataframes de una vez en un diccionario (la hice con comprehentions porque ando tambien practicando este tema 😄)

def read_sheets(data, skip_rows, sheets_list):
    
    sheets = { sheet_name: pd.read_excel(data, sheet_name=sheet_name, skiprows=skip_rows) for sheet_name in list(sheets_list)}

    return sheets

Data es la ruta donde estan los datos, skip_rows es la cantidad de filas que debe saltar para leer esos datos y sheets_list es una lista con los nombres de todas las hojas de calculo que quiero transformar en dataframes, de esta forma puedo tener toda la data llamando una sola vez la funcion

#List with the name of the sheets on the data file
sheet_names = ["GASTOS VARIOS", "CONTRATISTAS Y FDO FED", "SERV PPROF", "COMUNICACION", "SERV. PERS."]

#Using a function to read and add all sheets into one dictionary
dataframes = read_sheets("./data/raw/12_DICIEMBRE_2020.xlsx", 5, sheet_names)

La lipieza que realice en mi dataset

Manipulación de Valores Numéricos:

Corrección del formato de valores numéricos:
La división de las columnas de tasas de cobertura bruta y neta por 100 (`data['tasa_cobertura_bruta'] = data['tasa_cobertura_bruta'] /data['tasa_cobertura_bruta'] = data['tasa_cobertura_bruta'] / 100) asegura que los porcentajes estén representados correctamente si

Normalización de Nombres de Columnas:

Renombrado de columnas:
Se utilizó data.rename()para renombrar columnas a nombres más descriptivos y claros, lo que facilita su comprensión y el análisis posterior. Por ejemplo, cambie de 'tasa_cobertura_bruta' a 'cobertura_bruta'.

Otras Acciones:

  • Verificación y ajuste de variables clave:
  • Se realizó una revisión para asegurar que las variables clave para el análisis estén en el formato correcto y tengan la precisión necesaria.
  • Guardar los Datos Limpios:
Guardado de datos limpios:
Finalmente,data.to_csv(). Este paso es crucial para conservar los datos preparados para análisis poster
  AÑO  CÓDIGO_DEPARTAMENTO  DEPARTAMENTO  POBLACIÓN_5_16  \
0    2011                    5     Antioquia         1288473   
1    2011                    8     Atlántico          523935   
2    2011                   11  Bogotá, D.C.         1479334   
3    2011                   13       Bolívar          496676   
4    2011                   15        Boyacá          300501   
..    ...                  ...           ...             ...   
391  2022                   91      Amazonas           23239   
392  2022                   94       Guainía           16612   
393  2022                   95      Guaviare           22538   
394  2022                   97        Vaupés           15585   
395  2022                   99       Vichada           33949   

     TASA_MATRICULACIÓN_5_16  COBERTURA_NETA  COBERTURA_NETA_TRANSICIÓN  \
0                      94.01           93.85                      70.28   
1                      99.32           99.05                      50.59   
2                      90.70           90.29                      68.63   
3                      91.57           91.40                      59.74   
4                      86.16           86.11                      63.36   
..                       ...             ...                        ...   
391                    77.25           77.24                      54.73   
392                    67.60           67.60                      52.02   
393                    80.14           80.13                      45.74   
394                    55.51           55.51                      37.19   
395                    66.99           66.98                      48.58   
...
394              4.20           0.5551  
395              5.19           0.6698  

[396 rows x 38 columns]
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

Anotar valor encima de un gráfico

Les dejo esta función que me sirvió para visualizar los datos exactos en los gráficos de barras. Además de una manera de implementarlo.

def annotate_bars(ax):
    """
    Anota el valor exacto encima de cada barra en un gráfico de barras.
    """
    for p in ax.patches:
        ax.annotate(f'{int(p.get_height())}',
                    (p.get_x() + p.get_width() / 2., p.get_height()),
                    ha='center', va='center',
                    xytext=(0, 10),
                    textcoords='offset points')

Implementación, ejemplo:

#Distribución de los contratos por año actualizado hasta agosto 9 de 2023 (Anno Cargue SECOP):
plt.figure(figsize=(10, 6))
ax = sns.countplot(data=df, x='Anno Cargue SECOP', palette='viridis')
plt.title('Distribución de Contratos por Año')
plt.ylabel('Número de Contratos')
annotate_bars(ax)
plt.show()

Resultado:

No he visto muchos cursos en los que se use jupyter lab, me alegra que este lo tenga

!ls no me funcionó ya que estaba manejando windows y se usa !dir

Yo creé mi base de datos usando web scraping para obtener información de vehículos en venta en MercadoLibre, en mi caso, los retos que encontré a la hora de limpiar los datos fueron:


  • Cambiar los tipos de datos: variables como el precio, el año y los kilómetros recorridos además de números, tenían otros caracteres, esto lo pude solucionar fácilmente con una función que me eliminaba dichos caracteres y convertía el tipo de dato a entero.

  • Datos duplicados: Inspeccionando la base de datos encontré que habían registros que tenían los mismos valores para todas las variables, excepto el link de la publicación, a partir de esto descubrí que efectivamente aunque los links fueran diferentes, llevaban a la misma publicación, por lo cual decidí eliminar los duplicados.

  • Datos Faltantes: la base de datos tenía valores nulos para el color, el tipo de transmisión, la capacidad del motor y el tipo de carrocería. Para la parte de la transmisión y la carrocería les asigné el valor a partir de el modelo de cada registro, el color decidí dejarlo así ya que por ahora no lo considero relevante para mi análisis, (pero lo voy a comprobar a medida que continuo con el proyecto) y la capacidad del motor también quiero corroborar que tan determinante es, ya que la gran mayoría de los registros no la contienen y no puedo determinarla a partir del modelo.

siempre me había preguntado que factores determinan en que momentos del año nacen mas personas, entonces estoy limpiando datos del dane que tienen varias variables como el estrato, edad y demás.

Por esto tube que hacer:

  • descargar los archivos txt con los datos y pasarlos a encoding utf-8
  • importarlos a pandas donde no pude unirlos porque los títulos de las columnas eran unos con mayúsculas y otros con minúsculas
  • para que el dataset no fuera tan grande elimine las filas que no tuvieran fecha de nacimiento ya que eran irrelevances para este caso
  • también me falta trasformar los datos categóricos de números a un valor mas intuitivo

que rico curso

Algo curioso que me paso con mis datos es que el dataset tenia 7558 filas y despues de eliminar los datos que estaban vacios solo me quedaron 235 filas la verdad no se que pensar jaja

esta editor es espcial para data es genial
se llama dataspell

El reto de limpieza es una actividad que parece que no va a acabar nunca, pero una vez terminada… FIUF. Se siente como el final de “Harry Potter y las reliquias de la muerte”: no sabes cómo va a terminar, pero el final es maravilloso y lleno de lecciones para la vida.

Para los que tuvieron problemas como yo en pasar de object a datatime les dejo este sencillo tutorial:
https://www.youtube.com/watch?v=9LbslWe9GXc&ab_channel=JohnOrtizOrdoñez

Trate de usar datos de mi trabajo cotidiano para practicar, pero no existian. Así que tuve que crear un ETL para irlos obteniendo. Ahora si puedo realizar el ejercicio.

#Para ver el numero de filas y columnas
df_compras_dic.shape
(1774, 11)