Al aprender ciencia de datos en 2020, Pandas fue una de las herramientas más populares. Aunque las nuevas herramientas se centran en mejorar las debilidades de Pandas en el manejo de conjuntos de datos muy grandes, sigo usando Pandas para muchas tareas de limpieza, procesamiento y análisis de datos. Sí, Pandas me dificulta trabajar con miles de millones de filas, pero definitivamente es más que suficiente para trabajar con cualquier cosa por debajo de eso.
Veo que Pandas se usa no solo para EDA o en portátiles sino también en sistemas de producción.
En este artículo, repasaré algunas operaciones de procesamiento y limpieza de datos para demostrar cuán capaz es Pandas.
Comencemos con el conjunto de datos, que contiene unidades de mantenimiento de existencias (SKU) y respuestas de API de búsqueda para estos SKU.
importar pandas como pd search_results = pd.read_csv(“search_results.csv”) search_results.head()
El resultado de la búsqueda es una lista de diccionarios y tiene este aspecto:
resultados_de_busqueda.loc[0, “search_result”]
“[{‘my_id’: ‘HBCV00007F5Y2B’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00007UPQBM’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00008I29IH’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00006U3ZYB’, ‘distance’: 0.8961254358291626, ‘entity’: {}},
{‘my_id’: ‘HBCV0000AFA4H6’, ‘distance’: 0.8702399730682373, ‘entity’: {}},
{‘my_id’: ‘HBCV00009CDGD4’, ‘distance’: 0.86175537109375, ‘entity’: {}},
{‘my_id’: ‘HBCV000046336T’, ‘distance’: 0.8594968318939209, ‘entity’: {}},
{‘my_id’: ‘HBCV00009QDZRT’, ‘distance’: 0.8572311997413635, ‘entity’: {}},
{‘my_id’: ‘HBCV00008E11P3’, ‘distance’: 0.8553324937820435, ‘entity’: {}},
{‘my_id’: ‘HBV00000C4IY6’, ‘distance’: 0.8539167642593384, ‘entity’: {}}]
…y quedan 5 entidades”
Como vemos en el resultado, no es una lista adecuada de formato de diccionario debido a la última parte (“… y quedan 5 entidades”). Además, se guarda como una sola cadena.
Para poder utilizarlo mejor, necesitamos convertirlo en una lista adecuada de diccionarios. La siguiente línea de código elimina la última parte dividiendo la cadena en “…” y realiza la primera división.
resultados_de_busqueda.loc[0, “search_result”].dividir(“…”)[0].banda()
Sin embargo, la salida sigue siendo una sola cadena. Podemos usar el módulo ast integrado de Python para convertirlo en una lista:
importar ast res = ast.literal_eval(search_results.loc[0, “search_result”].dividir(“…”)[0].strip()) resolución
[{‘my_id’: ‘HBCV00007F5Y2B’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00007UPQBM’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00008I29IH’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00006U3ZYB’, ‘distance’: 0.8961254358291626, ‘entity’: {}},
{‘my_id’: ‘HBCV0000AFA4H6’, ‘distance’: 0.8702399730682373, ‘entity’: {}},
{‘my_id’: ‘HBCV00009CDGD4’, ‘distance’: 0.86175537109375, ‘entity’: {}},
{‘my_id’: ‘HBCV000046336T’, ‘distance’: 0.8594968318939209, ‘entity’: {}},
{‘my_id’: ‘HBCV00009QDZRT’, ‘distance’: 0.8572311997413635, ‘entity’: {}},
{‘my_id’: ‘HBCV00008E11P3’, ‘distance’: 0.8553324937820435, ‘entity’: {}},
{‘my_id’: ‘HBV00000C4IY6’, ‘distance’: 0.8539167642593384, ‘entity’: {}}]
Ahora tenemos los resultados de la búsqueda como una lista adecuada de diccionarios. Esto fue sólo para una sola fila. Necesitamos aplicar la misma operación a todos los SKU (es decir, a toda la columna de SKU).
Una opción es repasar todas las filas en un bucle for y realizar la misma operación. Sin embargo, esta no es la mejor opción. Deberíamos preferir operaciones vectorizadas cuando podamos. Una operación vectorizada básicamente significa ejecutar el código en todas las filas a la vez.
En una sola fila, utilicé la división para deshacerme de la última parte de la cadena, pero no funcionó en una operación vectorizada. Una opción más sólida parece ser utilizar una expresión regular.
resultados_de_busqueda.loc[:, ‘search_result’] = resultados_búsqueda[‘search_result’].str.replace(r”\.\.\..*”, “”, expresión regular=True).str.strip()
Este código selecciona “…” y todo lo que viene después y los reemplaza por nada. En otras palabras, elimina la parte “… y quedan 5 entidades”.
Ahora tenemos todas las filas de la columna de resultados de búsqueda como una lista adecuada de diccionarios.
resultados_de_busqueda.loc[10, “search_result”]
“[{‘my_id’: ‘HBCV00007F5Y2B’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00007UPQBM’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00008I29IH’, ‘distance’: 1.0, ‘entity’: {}},
{‘my_id’: ‘HBCV00006U3ZYB’, ‘distance’: 0.8961254358291626, ‘entity’: {}},
{‘my_id’: ‘HBCV0000AFA4H6’, ‘distance’: 0.8702399730682373, ‘entity’: {}},
{‘my_id’: ‘HBCV00009CDGD4’, ‘distance’: 0.86175537109375, ‘entity’: {}},
{‘my_id’: ‘HBCV000046336T’, ‘distance’: 0.8594968318939209, ‘entity’: {}},
{‘my_id’: ‘HBCV00009QDZRT’, ‘distance’: 0.8572311997413635, ‘entity’: {}},
{‘my_id’: ‘HBCV00008E11P3’, ‘distance’: 0.8553324937820435, ‘entity’: {}},
{‘my_id’: ‘HBV00000C4IY6’, ‘distance’: 0.8539167642593384, ‘entity’: {}}]”
Todavía están guardados como una cadena, pero puedo convertirlos fácilmente en una lista usando el módulo ast, lo cual haré en el siguiente paso.
Lo que me interesa son los SKU que aparecen en los resultados de búsqueda. Crearé una nueva columna extrayendo los SKU en los diccionarios. Puedo acceder a ellos usando la clave “my_id” del diccionario.
Hay 3 partes de esta operación:
Convierta la cadena de resultados de la búsqueda en una lista usando la función literal_eval. Extraiga SKU de la clave my_id del diccionario. Haga esto en una lista por comprensión para obtener SKU de todos los diccionarios de la lista.
Podemos realizar todas estas operaciones aplicando una función lambda a todas las filas de la siguiente manera:
resultados_de_busqueda.loc[:, “result_skus”] =\resultados_búsqueda[“search_result”].aplicar(lambda x: [item[‘my_id’] para el elemento en ast.literal_eval(x)]) search_results.head()
Cada fila de la columna result_skus contiene una lista de 10 SKU. Digamos que necesito tener estos 10 SKU en filas diferentes. Para cada fila de la columna sku, se crearán 10 filas a partir de la lista de la columna result_skus. Hay una forma muy sencilla de hacer esto en Pandas, que es la función de explosión.
datos = resultados_búsqueda[[“sku”, “result_skus”]].explode(“result_skus”, ignore_index=True) data.head()
Creamos un nuevo marco de datos con sku y columna result_skus. El siguiente dibujo demuestra lo que hace la función de explosión:
Consideremos lo contrario. Tenemos un marco de datos como se muestra arriba, pero queremos tener todos los resultados de un SKU en una sola fila.
Podemos usar la función groupby para agrupar las filas por sku y luego aplicar la función de lista en la columna result_skus:
new_data = datos.groupby(“sku”, as_index=False)[“result_skus”].apply(lista) new_data.head()
Esto nos llevará de nuevo al paso anterior:
Usando la función de explosión, creamos un marco de datos con una fila separada para cada sku en la columna result_skus. ¿Qué pasa si necesitamos separarlos en diferentes columnas en lugar de filas?
Una opción es aplicar la función pd.Series a la columna result_skus y concatenar las columnas resultantes al marco de datos original.
nuevas_cols = nuevos_datos[“result_skus”].apply(pd.Series) new_data = pd.concat([new_data, new_cols]eje=1) new_data.head()
Las columnas del 0 al 9 contienen los 10 SKU en la columna result_skus. Este código que utiliza la función de aplicación no es una operación vectorizada.
Tenemos otra opción, que está vectorizada y mucho más rápida.
nuevas_cols = pd.DataFrame(nuevos_datos[“result_skus”].tolist()) new_data = pd.concat([new_data, new_cols]eje=1)
Este código nos dará el mismo marco de datos que el anterior pero mucho más rápido.
Demostré una tarea típica de limpieza y procesamiento de datos que un científico o analista de datos puede encontrar en su trabajo. He estado en el campo durante más de 5 años y Pandas siempre ha sido suficiente para hacer lo que necesito, excepto cuando trabajo con conjuntos de datos muy grandes (por ejemplo, miles de millones de filas).
Las herramientas que se adaptan mejor a conjuntos de datos tan grandes tienen una sintaxis similar a la de Pandas. Por ejemplo, PySpark es una especie de mezcla de Pandas y SQL. Polars es muy similar a Pandas en términos de sintaxis. Por lo tanto, aprender y practicar Pandas sigue siendo una habilidad muy valiosa para cualquiera que trabaje en el dominio de la ciencia de datos y la inteligencia artificial.
Gracias por leer.