<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Evolve</title>
    <description>The latest articles on DEV Community by Evolve (@evolve-space).</description>
    <link>https://dev.to/evolve-space</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F13182%2F181b19dd-cb59-49d1-a5ef-f7e8087a388b.jpg</url>
      <title>DEV Community: Evolve</title>
      <link>https://dev.to/evolve-space</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/evolve-space"/>
    <language>en</language>
    <item>
      <title>10.430 muertes, 10 preguntas y un pipeline en Python: lo que los datos de violencia policial en EE.UU. no te cuentan a simple vista</title>
      <dc:creator>David Naranjo Ramírez</dc:creator>
      <pubDate>Wed, 27 May 2026 16:40:01 +0000</pubDate>
      <link>https://dev.to/evolve-space/10430-muertes-10-preguntas-y-un-pipeline-en-python-lo-que-los-datos-de-violencia-policial-en-54j6</link>
      <guid>https://dev.to/evolve-space/10430-muertes-10-preguntas-y-un-pipeline-en-python-lo-que-los-datos-de-violencia-policial-en-54j6</guid>
      <description>&lt;p&gt;Cuando el Washington Post empezó a contar los muertos en 2015, el FBI subestimaba casi el 50% de los casos. Ese dato me enganchó. No por el morbo, sino por lo que implica metodológicamente: si los registros oficiales fallan de manera tan estrepitosa, ¿qué más se pierde cuando no miras bien los datos?&lt;/p&gt;

&lt;p&gt;Ese fue el punto de partida de &lt;strong&gt;EDAFatalForce&lt;/strong&gt;, mi proyecto de Análisis Exploratorio de Datos del Máster de Data Science en Evolve.&lt;/p&gt;




&lt;h2&gt;
  
  
  El dataset: periodismo de datos como fuente primaria
&lt;/h2&gt;

&lt;p&gt;El core del proyecto es la base de datos &lt;strong&gt;Fatal Force&lt;/strong&gt; del Washington Post — 10.430 incidentes fatales entre 2015 y 2024 con variables como raza, edad, armamento, comportamiento de fuga, nivel de amenaza percibida y si el agente llevaba cámara corporal.&lt;/p&gt;

&lt;p&gt;Para enriquecerlo crucé tres fuentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Census Bureau ACS 2020&lt;/strong&gt; — datos socioeconómicos de 3.221 condados (ingresos, pobreza, desempleo)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NCSL&lt;/strong&gt; — políticas de cámara corporal por estado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabla FIPS&lt;/strong&gt; — para enlazar condados con el Census&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El mayor desafío no fue el modelado. Fue la calidad del dato. El &lt;strong&gt;45% de los registros no tenía condado&lt;/strong&gt;, lo que bloqueaba cualquier join con el Census. La solución: construir internamente un mapa &lt;code&gt;ciudad + estado → condado&lt;/code&gt; usando la moda de los registros que sí lo tenían. Resultado: de 45% de nulos a 17,4%. Un cambio que desbloqueó más de 2.800 filas para el análisis socioeconómico.&lt;/p&gt;




&lt;h2&gt;
  
  
  El proceso: bugs, fixes y un pipeline modular
&lt;/h2&gt;

&lt;p&gt;El proyecto está estructurado como un pipeline reproducible en &lt;code&gt;src/&lt;/code&gt;: limpieza → enriquecimiento → feature engineering → EDA. Un solo &lt;code&gt;python main.py&lt;/code&gt; lo ejecuta todo, incluyendo la descarga del Census.&lt;/p&gt;

&lt;p&gt;Durante la auditoría encontré dos bugs críticos en el feature engineering que hubieran invalidado análisis completos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug 1 — La paradoja de la fuga estaba rota.&lt;/strong&gt; El valor raw &lt;code&gt;"not"&lt;/code&gt; (53% de los registros) no coincidía con la regex diseñada para mapear "no huía", así que más de 5.500 víctimas que no huían quedaban clasificadas como comportamiento desconocido. La pregunta Q2 entera era inválida.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bug 2 — "Undetermined" contaba como armado.&lt;/strong&gt; Los 463 registros con armamento &lt;code&gt;"undetermined"&lt;/code&gt; heredaban &lt;code&gt;is_armed = 1.0&lt;/code&gt; por caer en el &lt;code&gt;default&lt;/code&gt; del &lt;code&gt;np.select&lt;/code&gt;. Víctimas con armamento desconocido aparecían como armadas en todas las tasas.&lt;/p&gt;

&lt;p&gt;Ambos fixes son de una línea. El impacto analítico, considerable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resultados: lo que los datos dicen y lo que no
&lt;/h2&gt;

&lt;p&gt;Diez preguntas, diez respuestas con tests estadísticos. Las más reveladoras:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l7gx4k7yionjv315u0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l7gx4k7yionjv315u0o.png" alt=" " width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El ranking de estados respecto a número de incidentes fatales cambia por completo al normalizar.&lt;/strong&gt; California lidera con +1200 incidentes brutos. Pero al dividir por población, Misisipi sube al primer puesto con 85,5 casos por 100.000 habitantes. El volumen engaña. La tasa informa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawc5t6scl78wgx7jpwou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawc5t6scl78wgx7jpwou.png" alt=" " width="799" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Los protocolos de crisis mental funcionan.&lt;/strong&gt; Los incidentes con signos de enfermedad mental presentan una tasa de amenaza letal del 35,3% frente al 44,4% del resto (χ²=55,18, p&amp;lt;0,001). El resultado más robusto estadísticamente de todo el análisis, y el más contraintuitivo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubvbcq3btinhpc8bl727.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubvbcq3btinhpc8bl727.png" alt=" " width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Huir en coche es más peligroso que no huir.&lt;/strong&gt; La tasa de amenaza letal resulta 4 puntos y medio porcentuales mayor en persecuciones vehiculares que en personas que no huyen. Un vehículo a alta velocidad es percibido como amenaza física directa, no solo como evasión.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo6uoanth1yomuhrrjso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo6uoanth1yomuhrrjso.png" alt=" " width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entre víctimas desarmadas, la raza sigue siendo predictora.&lt;/strong&gt; Las víctimas negras desarmadas tienen una tasa letal 4,2 puntos superior a las blancas (χ²=11,65, p=0,003). &lt;code&gt;threat_level&lt;/code&gt; es la narrativa del agente, no un hecho verificado — esa limitación es parte del análisis, no una nota al pie.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lo que aprendí
&lt;/h2&gt;

&lt;p&gt;Que los bugs de feature engineering son los más peligrosos porque no rompen el código — producen resultados plausibles pero incorrectos. Y que documentar las limitaciones no debilita un análisis: lo hace honesto y, paradójicamente, más creíble.&lt;/p&gt;

&lt;p&gt;Si lo repitiera, integraría coordenadas lat/lon para análisis espaciales con DBSCAN geográfico. Los hotspots por condado cuentan la mitad de la historia; los hotspots dentro del condado contarían la otra.&lt;/p&gt;




&lt;p&gt;📁 Repo completo en GitHub: https://github.com/dnarram/Proyecto-Master-DataScience-Evolve-DavidNaranjoRamirez-EDAFatalForce&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Proyecto desarrollado durante el &lt;a href="https://evolve.es" rel="noopener noreferrer"&gt;Máster en Data Science de Evolve&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>panda</category>
      <category>jupyter</category>
    </item>
    <item>
      <title>Construyendo un recomendador de películas en Python: de los datos al modelo</title>
      <dc:creator>Alberto Martinez</dc:creator>
      <pubDate>Mon, 25 May 2026 18:22:03 +0000</pubDate>
      <link>https://dev.to/evolve-space/construyendo-un-recomendador-de-peliculas-en-python-de-los-datos-al-modelo-3m16</link>
      <guid>https://dev.to/evolve-space/construyendo-un-recomendador-de-peliculas-en-python-de-los-datos-al-modelo-3m16</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Los sistemas de recomendación están presentes en muchas plataformas digitales: streaming, e-commerce, música, formación online o personalización de contenidos. Su objetivo es ayudar al usuario a descubrir elementos relevantes dentro de catálogos cada vez más grandes.&lt;/p&gt;

&lt;p&gt;En este proyecto he desarrollado &lt;strong&gt;CineMatch AI&lt;/strong&gt;, un sistema de recomendación de películas basado en filtrado colaborativo por ítems. La idea principal es sencilla: dada una película de referencia, el sistema recomienda otras películas similares a partir de los patrones históricos de valoración de los usuarios.&lt;/p&gt;

&lt;p&gt;El objetivo no era construir una solución empresarial completa, sino un prototipo funcional, reproducible y bien estructurado que permitiera trabajar un flujo completo de Data Science: análisis de datos, preprocesamiento, construcción del sistema de recomendación, evaluación exploratoria y presentación mediante una interfaz sencilla.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dataset utilizado
&lt;/h2&gt;

&lt;p&gt;Para el proyecto he utilizado el dataset &lt;strong&gt;MovieLens&lt;/strong&gt;, una referencia habitual para trabajar con sistemas de recomendación.&lt;/p&gt;

&lt;p&gt;El conjunto de datos incluye información sobre películas, usuarios y valoraciones. En este caso, el trabajo se ha centrado principalmente en dos archivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ratings.csv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;movies.csv&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tras el proceso de filtrado, el sistema trabaja con:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;446.702 ratings finales&lt;/li&gt;
&lt;li&gt;3.728 películas&lt;/li&gt;
&lt;li&gt;4.356 usuarios activos&lt;/li&gt;
&lt;li&gt;una matriz usuario-película con una densidad aproximada del 2,75%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este último punto es importante, porque en los sistemas de recomendación es habitual trabajar con matrices muy dispersas: muchos usuarios han valorado solo una pequeña parte del catálogo total.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proceso seguido
&lt;/h2&gt;

&lt;p&gt;El flujo del proyecto se divide en varias fases.&lt;/p&gt;

&lt;p&gt;Primero se realizó la carga y exploración inicial de los datos, revisando el volumen de registros, la distribución de ratings y la información disponible sobre las películas.&lt;/p&gt;

&lt;p&gt;Después se aplicaron filtros para mejorar la calidad de las recomendaciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;películas con al menos 20 valoraciones.&lt;/li&gt;
&lt;li&gt;usuarios con al menos 10 valoraciones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este filtrado reduce ruido y evita que el sistema se base en películas o usuarios con muy poca información histórica.&lt;/p&gt;

&lt;p&gt;A continuación se construyó una matriz usuario-película, donde cada fila representa un usuario, cada columna una película y cada valor corresponde a la puntuación asignada. A partir de esta matriz, el sistema compara películas entre sí usando &lt;strong&gt;similitud del coseno&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La lógica es la siguiente: si dos películas han sido valoradas de forma parecida por muchos usuarios, el sistema interpreta que existe cierta similitud entre ellas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sistema de recomendación
&lt;/h2&gt;

&lt;p&gt;El recomendador está basado en &lt;strong&gt;filtrado colaborativo por ítems&lt;/strong&gt;. En lugar de comparar usuarios entre sí, compara películas a partir de los patrones de valoración.&lt;/p&gt;

&lt;p&gt;Este enfoque tiene varias ventajas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;es fácil de explicar.&lt;/li&gt;
&lt;li&gt;funciona bien cuando existen suficientes valoraciones.&lt;/li&gt;
&lt;li&gt;permite generar recomendaciones interpretables.&lt;/li&gt;
&lt;li&gt;puede adaptarse a otros dominios como productos, canciones, cursos o contenidos digitales.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además del análisis en notebook, el proyecto incluye una pequeña aplicación con &lt;strong&gt;Streamlit&lt;/strong&gt;, pensada para probar el sistema de forma visual. Desde la interfaz se puede buscar una película, seleccionar una coincidencia del catálogo y obtener un top 5 o top 10 de recomendaciones con su score de similitud.&lt;/p&gt;

&lt;p&gt;También se incluye una API básica con &lt;strong&gt;FastAPI&lt;/strong&gt; como demostración complementaria de cómo podría exponerse la lógica del recomendador.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;p&gt;El sistema genera recomendaciones coherentes, especialmente para películas con suficientes valoraciones históricas.&lt;/p&gt;

&lt;p&gt;Algunos resultados principales del análisis fueron:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;matriz usuario-película de 4.356 usuarios por 3.728 películas.&lt;/li&gt;
&lt;li&gt;446.702 ratings utilizados tras el filtrado.&lt;/li&gt;
&lt;li&gt;similitud media top-N de 0,5662.&lt;/li&gt;
&lt;li&gt;consistencia media de géneros del 81,5%.&lt;/li&gt;
&lt;li&gt;94 de 100 películas evaluadas con una consistencia de géneros superior al 50%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por ejemplo, para una película como &lt;code&gt;Scarface (1983)&lt;/code&gt;, el sistema recomienda títulos relacionados con géneros como crimen, drama, thriller o acción, lo que muestra una cierta coherencia temática en las recomendaciones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitaciones
&lt;/h2&gt;

&lt;p&gt;Como ocurre en muchos sistemas de recomendación, el proyecto también tiene limitaciones.&lt;/p&gt;

&lt;p&gt;La más importante es el problema de &lt;strong&gt;cold start&lt;/strong&gt;: si una película o usuario no tiene valoraciones suficientes, el sistema no dispone de información histórica para generar recomendaciones fiables.&lt;/p&gt;

&lt;p&gt;Además, el filtrado por popularidad mejora la calidad de las recomendaciones, pero reduce la cobertura total del catálogo. También hay que tener en cuenta que el sistema recomienda a partir de patrones históricos de valoración, no por una comprensión semántica profunda del contenido de las películas.&lt;/p&gt;

&lt;p&gt;Por último, la evaluación realizada es exploratoria. No debe interpretarse como una evaluación supervisada definitiva, ya que no se ha aplicado una separación train/test ni métricas de ranking como Precision@K, Recall@K o NDCG, habituales en la evaluación de sistemas de recomendación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprendizajes
&lt;/h2&gt;

&lt;p&gt;Este proyecto me ha servido para entender mejor cómo se estructura un sistema de recomendación desde una perspectiva práctica.&lt;/p&gt;

&lt;p&gt;Más allá de la técnica de similitud, una parte importante del trabajo ha estado en preparar los datos, tomar decisiones de filtrado, construir una estructura reproducible y presentar los resultados de forma clara.&lt;/p&gt;

&lt;p&gt;También me ha parecido especialmente interesante comprobar cómo una técnica relativamente sencilla, como la similitud del coseno, puede generar recomendaciones razonables cuando los datos están bien tratados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos pasos
&lt;/h2&gt;

&lt;p&gt;Algunas mejoras naturales para futuras versiones serían:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;combinar ratings y géneros en un sistema híbrido.&lt;/li&gt;
&lt;li&gt;incorporar técnicas de factorización matricial como SVD o NMF.&lt;/li&gt;
&lt;li&gt;mejorar la evaluación offline con métricas de ranking.&lt;/li&gt;
&lt;li&gt;guardar la matriz de similitud precomputada para acelerar la demo.&lt;/li&gt;
&lt;li&gt;desplegar la aplicación para facilitar su uso externo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repositorio
&lt;/h2&gt;

&lt;p&gt;El código completo del proyecto está disponible en GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/evolve-space/Proyecto-Master-DataScience-Evolve-AlbertoMartinez" rel="noopener noreferrer"&gt;https://github.com/evolve-space/Proyecto-Master-DataScience-Evolve-AlbertoMartinez&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podeis contactarme en mi LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/albertomartinezsanchez" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/albertomartinezsanchez&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Proyecto desarrollado durante el Máster en Data Science &amp;amp; Desarrollo de IA de Evolve.&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>machinelearning</category>
      <category>streamlit</category>
    </item>
    <item>
      <title>What 3.9M powerlifting records tell us about competition strategy — an EDA with Python</title>
      <dc:creator>Rubén Gil</dc:creator>
      <pubDate>Sat, 23 May 2026 20:02:03 +0000</pubDate>
      <link>https://dev.to/evolve-space/what-39m-powerlifting-records-tell-us-about-competition-strategy-an-eda-with-python-5g6k</link>
      <guid>https://dev.to/evolve-space/what-39m-powerlifting-records-tell-us-about-competition-strategy-an-eda-with-python-5g6k</guid>
      <description>&lt;p&gt;&lt;strong&gt;What 3.9M powerlifting records tell us about competition strategy — an EDA with Python&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;When I started this EDA project for my Data Science Master at &lt;a href="https://evolve.es" rel="noopener noreferrer"&gt;Evolve&lt;/a&gt;, I picked the Open Powerlifting dataset because beyond being a gym-rat, I've always been curious about the competition strategy in powerlifting.&lt;/p&gt;




&lt;h2&gt;
  
  
  The dataset
&lt;/h2&gt;

&lt;p&gt;Open Powerlifting is an open-source project that tracks powerlifting competition results worldwide. The full dataset has ~3.9M rows and 42 columns covering athlete info, every single lift attempt, and performance metrics.&lt;/p&gt;

&lt;p&gt;Before any analysis I filtered it down to sanctioned, drug-tested competitions only and kept only the columns I'd actually use. The main challenge: &lt;strong&gt;negative values mean a failed lift&lt;/strong&gt;, not bad data. That required building boolean columns to track success/failure before converting negatives to NaN.&lt;/p&gt;




&lt;h2&gt;
  
  
  The process
&lt;/h2&gt;

&lt;p&gt;Fully modularized in Python using pandas, numpy, seaborn, matplotlib and pingouin. The pipeline runs end-to-end from &lt;code&gt;main.py&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;raw CSV → filter → clean → features → assert → analyze&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Imputation was done conservatively; age from AgeClass ranges, bodyweight from weight class, never synthetic values. Also, NaN values were filtered dynamically for each question.&lt;/p&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqc7cvcav5uaidjpe614i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqc7cvcav5uaidjpe614i.png" alt="DOTS metric vs age to show performance by age and sex" width="799" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peak performance age:&lt;/strong&gt; Athletes peak between 22-24 years old and decline steadily after. No meaningful difference between men and women once normalized by bodyweight.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0imcoyq0clik93pnskdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0imcoyq0clik93pnskdg.png" alt="Fail rates at third lift for Squat, Bench and Deadlift" width="799" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where do athletes fail most?&lt;/strong&gt; Bench press has a &lt;strong&gt;54% fail rate&lt;/strong&gt; on the 3rd attempt. Squat and deadlift sit around 36-40%. The gap is consistent across sexes and equipment types — bench just behaves differently.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hls5sep3unkziw5jh0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hls5sep3unkziw5jh0c.png" alt="Success rate for 4th attempt for Squat, Bench and Deadlift" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The 4th attempt:&lt;/strong&gt; When athletes take a 4th attempt, they succeed &lt;strong&gt;~77% of the time&lt;/strong&gt; on average. Deadlift leads at 83%. This is the most actionable insight of the whole project — just take the 4th attempt.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;About powerlifting&lt;/strong&gt;&lt;br&gt;
Athletes peak between 22-24, always take the 4th attempt and make sure you won't fail the 3rd one, it can change the whole competition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About analysing data&lt;/strong&gt;&lt;br&gt;
If you have enough data, maybe it's better to not fill the gaps with artificial values. Also, some features must be built before cleaning or you'll spend an hour chating with AI wondering why all your booleans are NaN.&lt;/p&gt;

&lt;p&gt;Full code: &lt;a href="https://github.com/rubengil-dev/power_lifting_analisis" rel="noopener noreferrer"&gt;github.com/rubengil-dev/power_lifting_analisis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Project developed during the Data Science Master at &lt;a href="https://evolve.es" rel="noopener noreferrer"&gt;Evolve&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>data</category>
      <category>sportscience</category>
    </item>
    <item>
      <title>De hojas de cálculo a IA: construyendo una plataforma SRM moderna</title>
      <dc:creator>Jose Martos</dc:creator>
      <pubDate>Fri, 22 May 2026 11:39:45 +0000</pubDate>
      <link>https://dev.to/evolve-space/de-hojas-de-calculo-a-ia-construyendo-una-plataforma-srm-moderna-5h2h</link>
      <guid>https://dev.to/evolve-space/de-hojas-de-calculo-a-ia-construyendo-una-plataforma-srm-moderna-5h2h</guid>
      <description>&lt;h1&gt;
  
  
  Cómo construí ProcureFlow AI: una plataforma SRM con IA y automatización empresarial
&lt;/h1&gt;

&lt;p&gt;Muchas pequeñas y medianas empresas siguen gestionando proveedores mediante hojas de cálculo, emails dispersos y procesos manuales difíciles de escalar. Cuando empecé a trabajar en ProcureFlow AI, quería resolver precisamente ese problema: crear una plataforma moderna que centralizara la gestión de proveedores y permitiera automatizar procesos internos usando inteligencia artificial.&lt;/p&gt;

&lt;p&gt;Lo interesante del proyecto no era únicamente desarrollar un panel administrativo, sino diseñar una arquitectura preparada para evolucionar hacia automatizaciones inteligentes reales. Quería construir algo cercano a un entorno empresarial moderno, donde frontend, backend, workflows y servicios de IA estuvieran desacoplados y listos para crecer.&lt;/p&gt;

&lt;p&gt;ProcureFlow AI nace como una solución SRM (Supplier Relationship Management), enfocada en digitalizar procesos relacionados con compras, proveedores y automatización operativa. A diferencia de los CRMs tradicionales centrados en clientes, este proyecto pone el foco en la organización interna y la eficiencia empresarial.&lt;/p&gt;

&lt;h2&gt;
  
  
  El entorno y la arquitectura del proyecto
&lt;/h2&gt;

&lt;p&gt;En este caso no trabajé con un dataset clásico de machine learning, sino con un entorno full stack orientado a procesos empresariales reales. El principal reto fue diseñar una arquitectura modular y flexible capaz de soportar múltiples funcionalidades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gestión centralizada de proveedores&lt;/li&gt;
&lt;li&gt;Automatización de procesos internos&lt;/li&gt;
&lt;li&gt;Integración de inteligencia artificial&lt;/li&gt;
&lt;li&gt;Sistema de autenticación y roles&lt;/li&gt;
&lt;li&gt;Infraestructura escalable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La aplicación fue desarrollada usando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React y Tailwind CSS para el frontend&lt;/li&gt;
&lt;li&gt;Symfony y PHP para el backend API REST&lt;/li&gt;
&lt;li&gt;MySQL como base de datos&lt;/li&gt;
&lt;li&gt;Docker para facilitar despliegue y desarrollo&lt;/li&gt;
&lt;li&gt;OpenAI API para integración de IA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La separación entre frontend, backend y servicios de automatización fue una decisión clave desde el principio, ya que quería evitar una arquitectura monolítica difícil de mantener en el futuro.&lt;/p&gt;

&lt;h2&gt;
  
  
  El proceso de desarrollo
&lt;/h2&gt;

&lt;p&gt;El desarrollo comenzó definiendo primero la estructura del backend y las entidades principales relacionadas con proveedores, usuarios y procesos internos. Una vez definida la API REST en Symfony, construí el frontend en React consumiendo los distintos endpoints.&lt;/p&gt;

&lt;p&gt;Uno de los aspectos más interesantes fue integrar automatización e inteligencia artificial dentro del flujo empresarial. En lugar de añadir IA “porque sí”, intenté enfocarla hacia casos de uso reales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Asistencia contextual&lt;/li&gt;
&lt;li&gt;Automatización de tareas repetitivas&lt;/li&gt;
&lt;li&gt;Generación de respuestas y apoyo operativo&lt;/li&gt;
&lt;li&gt;Preparación para workflows inteligentes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otro reto importante fue diseñar un sistema fácilmente desplegable. Para ello trabajé con Docker y una arquitectura separada por servicios, lo que permitió mantener frontend y backend desacoplados y facilitar futuras migraciones a producción.&lt;/p&gt;

&lt;p&gt;También dediqué bastante tiempo al diseño responsive y a la experiencia de usuario. Muchas herramientas empresariales tienen interfaces antiguas o demasiado complejas, así que quería crear algo visualmente moderno y fácil de usar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultados obtenidos
&lt;/h2&gt;

&lt;p&gt;El resultado final fue una plataforma full stack funcional desplegada en producción con una arquitectura preparada para escalar y evolucionar.&lt;/p&gt;

&lt;p&gt;Entre las funcionalidades implementadas destacan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dashboard administrativo&lt;/li&gt;
&lt;li&gt;Gestión completa de proveedores&lt;/li&gt;
&lt;li&gt;Sistema de autenticación&lt;/li&gt;
&lt;li&gt;Integración con IA&lt;/li&gt;
&lt;li&gt;Arquitectura modular&lt;/li&gt;
&lt;li&gt;Automatización empresarial&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además, el proyecto incluye un entorno demo funcional accesible públicamente, algo que me permitió trabajar también aspectos relacionados con despliegue y DevOps.&lt;/p&gt;

&lt;p&gt;Uno de los aprendizajes más importantes fue entender cómo organizar correctamente una arquitectura empresarial moderna. Antes de este proyecto tendía a pensar más en funcionalidades aisladas; aquí empecé a enfocarme realmente en escalabilidad, separación de responsabilidades y mantenibilidad.&lt;/p&gt;

&lt;p&gt;También aprendí bastante sobre integración de APIs de IA en aplicaciones reales. Muchas veces desde fuera parece sencillo conectar modelos LLM, pero el verdadero desafío está en integrarlos dentro de flujos útiles para negocio.&lt;/p&gt;

&lt;p&gt;Si tuviera que continuar el proyecto, el siguiente paso lógico sería implementar agentes inteligentes y workflows más avanzados, además de integración con ERPs externos y automatización documental.&lt;/p&gt;

&lt;p&gt;Repositorio del proyecto:&lt;br&gt;
GitHub: &lt;a href="https://github.com/evolve-space/Proyecto-Master-IA-Evolve-JoseMartos.git" rel="noopener noreferrer"&gt;https://github.com/evolve-space/Proyecto-Master-IA-Evolve-JoseMartos.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo:&lt;br&gt;
&lt;a href="https://srm-compras-front.vercel.app/" rel="noopener noreferrer"&gt;https://srm-compras-front.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imágenes:&lt;/p&gt;

&lt;p&gt;Dashboard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc9b4gb8jc6wq319gfvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc9b4gb8jc6wq319gfvu.png" alt=" " width="799" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gestión de proveedores:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyur12t2wbhsq840e7ktx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyur12t2wbhsq840e7ktx.png" alt=" " width="799" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ProcureFlow AI fue desarrollado como proyecto académico durante el Máster en Inteligencia Artificial de &lt;a href="https://evolve.es?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Evolve&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>showdev</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Luxury and nationalities, my first data science project!</title>
      <dc:creator>Miriam</dc:creator>
      <pubDate>Fri, 22 May 2026 06:59:53 +0000</pubDate>
      <link>https://dev.to/evolve-space/luxury-and-nationalities-my-first-data-science-project-1hf1</link>
      <guid>https://dev.to/evolve-space/luxury-and-nationalities-my-first-data-science-project-1hf1</guid>
      <description>&lt;p&gt;Good morning everyone!&lt;br&gt;
I'm happy to announce that yesterday I finished my first project in data science!&lt;br&gt;
I link here the github repository. &lt;br&gt;
This project, based on the dataset "515K Hotel Reviews Data in Europe" from Jiashen Liu, analyzes the level of demand required by luxury tourism depending on the different nationalities, through Sentiment Analysis and Natural Language Processing.&lt;/p&gt;

&lt;p&gt;This is my first project, as I mentioned, so I would appreciate any feedback.&lt;br&gt;
I'm very confident that this is the right path for me, and I want to do everything I can to improve and become a competent data analyst.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Miris-01/evolve-project-01" rel="noopener noreferrer"&gt;Here is the repo!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, I want to say thank you to my professor and classmates from Evolve!&lt;/p&gt;

&lt;p&gt;Read you soon!&lt;/p&gt;

&lt;p&gt;Miriam.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>jupyter</category>
      <category>nlp</category>
    </item>
    <item>
      <title>ENS Readiness Assistant — Automatizando evaluaciones de adecuación al ENS con HTML, CSS y JavaScript</title>
      <dc:creator>Himardlg</dc:creator>
      <pubDate>Tue, 19 May 2026 08:07:29 +0000</pubDate>
      <link>https://dev.to/evolve-space/ens-readiness-assistant-automatizando-evaluaciones-de-adecuacion-al-ens-con-html-css-y-javascript-5ah5</link>
      <guid>https://dev.to/evolve-space/ens-readiness-assistant-automatizando-evaluaciones-de-adecuacion-al-ens-con-html-css-y-javascript-5ah5</guid>
      <description>&lt;p&gt;Quizás no sean el mejor programador de los presentes en esta organización, soy un perfil mas técnico, pero seguramente de lo que mas le gustan los retos y desafíos. &lt;br&gt;
Uno de los mayores retos en proyectos GRC es convertir normativa compleja en algo accionable para las organizaciones.&lt;br&gt;
El Esquema Nacional de Seguridad (RD 311/2022) es obligatorio para la Administración Pública española y sus proveedores tecnológicos — pero muchas entidades no saben por dónde empezar, qué categoría les corresponde ni qué controles tienen que implementar.&lt;br&gt;
Por eso construí ENS Readiness Assistant. &lt;br&gt;
&lt;strong&gt;¿Qué es?&lt;/strong&gt;&lt;br&gt;
Una herramienta web que guía a cualquier organización a través de una evaluación de adecuación al ENS en 4 pasos y genera un informe con sus brechas y recomendaciones concretas.&lt;br&gt;
Sin instalación. Sin backend. Sin dependencias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Qué hace exactamente?&lt;/strong&gt;&lt;br&gt;
Paso 1 — Datos de la organización&lt;br&gt;
Determina el tipo de entidad y sector para saber si el ENS aplica según el Art. 2 del RD 311/2022. No todas las organizaciones están obligadas — la herramienta lo aclara desde el principio.&lt;br&gt;
Paso 2 — Sistemas y servicios&lt;br&gt;
Evalúa el tipo de información gestionada y el impacto potencial de un incidente para determinar la categoría del sistema: Básica, Media o Alta.&lt;br&gt;
Paso 3 — Estado de controles&lt;br&gt;
Checklist de 10 controles clave del Anexo II del ENS con tres estados posibles: implementado, parcialmente implementado o no implementado.&lt;br&gt;
Paso 4 — Informe de resultados&lt;br&gt;
Genera automáticamente:&lt;/p&gt;

&lt;p&gt;✅ Si el ENS aplica o no y por qué&lt;br&gt;
🏷️ Categoría del sistema calculada&lt;br&gt;
📊 Porcentaje de cumplimiento actual&lt;br&gt;
🔍 Gap analysis con brechas por prioridad Alta / Media / Baja&lt;br&gt;
💡 Recomendaciones con plazos estimados de implementación&lt;br&gt;
🖨️ Exportación a PDF mediante impresión del navegador&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tecnología utilizada&lt;/strong&gt;&lt;br&gt;
MVP v1.0 construido con HTML, CSS y JavaScript vanilla — sin frameworks, sin backend, sin dependencias externas. Desplegado en GitHub Pages.&lt;br&gt;
La decisión fue deliberada — quería publicar rápido, aprender haciendo y que cualquiera pudiera clonar el repo y ejecutarlo abriendo un solo archivo HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que aprendí construyéndolo&lt;/strong&gt;&lt;br&gt;
Transformar normativa en lógica técnica es más complejo de lo que parece.&lt;br&gt;
Cada artículo del RD 311/2022 tiene matices que dependen del tipo de organización, la categoría del sistema y las dimensiones de seguridad afectadas. Por ejemplo, la obligación de usar MFA no es universal — aplica a accesos remotos en sistemas de categoría Media y Alta, no en todos los casos.&lt;br&gt;
Ese proceso de traducción normativa → lógica → código es exactamente el núcleo del trabajo GRC. Y construir esta herramienta me obligó a entenderlo de verdad, no solo a nivel teórico.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/evolve-space/ENS-Readiness-Assistant-Himardeleongonzalez" rel="noopener noreferrer"&gt;Proyecto ENS-Readiness-Assistant&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cybersecurity</category>
      <category>grc</category>
      <category>compliance</category>
    </item>
    <item>
      <title>RedRecruit: Cómo construí una plataforma de empleo en ciberseguridad con Python, Flask y Stripe</title>
      <dc:creator>Pablo Díaz</dc:creator>
      <pubDate>Mon, 18 May 2026 15:47:44 +0000</pubDate>
      <link>https://dev.to/evolve-space/redrecruit-como-construi-una-plataforma-de-empleo-en-ciberseguridad-con-python-flask-y-stripe-mio</link>
      <guid>https://dev.to/evolve-space/redrecruit-como-construi-una-plataforma-de-empleo-en-ciberseguridad-con-python-flask-y-stripe-mio</guid>
      <description>&lt;h1&gt;
  
  
  RedRecruit: Cómo construí una plataforma de empleo en ciberseguridad con Python, Flask y Stripe
&lt;/h1&gt;

&lt;p&gt;La mayoría de plataformas de empleo actuales son demasiado genéricas para perfiles técnicos especializados en ciberseguridad. Quería crear una aplicación enfocada específicamente en este sector, donde los usuarios pudieran buscar vacantes relevantes, gestionar su cuenta de forma segura y acceder a funcionalidades premium dentro de una experiencia moderna y profesional.&lt;/p&gt;

&lt;p&gt;Con ese objetivo nació RedRecruit, una plataforma desarrollada con Flask que combina autenticación segura, integración de pagos con Stripe y consumo de APIs reales de empleo orientadas al sector tecnológico y de ciberseguridad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack tecnológico
&lt;/h2&gt;

&lt;p&gt;Estas son las principales tecnologías utilizadas durante el desarrollo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3&lt;/li&gt;
&lt;li&gt;Flask&lt;/li&gt;
&lt;li&gt;Flask-Login&lt;/li&gt;
&lt;li&gt;Flask-Bcrypt&lt;/li&gt;
&lt;li&gt;Stripe Checkout&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;HTML/CSS&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;Requests&lt;/li&gt;
&lt;li&gt;itsdangerous&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Funcionalidades principales
&lt;/h2&gt;

&lt;p&gt;La aplicación incluye múltiples funcionalidades orientadas a una experiencia realista de plataforma SaaS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Búsqueda de vacantes en ciberseguridad usando APIs reales&lt;/li&gt;
&lt;li&gt;Resultados organizados en páginas dedicadas&lt;/li&gt;
&lt;li&gt;Registro y login de usuarios&lt;/li&gt;
&lt;li&gt;Verificación de email y recuperación de contraseña&lt;/li&gt;
&lt;li&gt;Integración premium mediante Stripe Checkout&lt;/li&gt;
&lt;li&gt;Panel admin protegido&lt;/li&gt;
&lt;li&gt;Navegación profesional mediante breadcrumbs&lt;/li&gt;
&lt;li&gt;Gestión de sesiones y perfiles&lt;/li&gt;
&lt;li&gt;Integración con APIs Adzuna y JSearch&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lo más técnico: autenticación y Stripe
&lt;/h2&gt;

&lt;p&gt;La parte más interesante del proyecto fue diseñar un sistema de autenticación seguro y combinarlo con una integración funcional de pagos online.&lt;/p&gt;

&lt;p&gt;Para la autenticación utilicé Flask-Login junto con Flask-Bcrypt para proteger las contraseñas mediante hashing seguro. Además, implementé verificación de email y recuperación de contraseña utilizando tokens temporales generados con &lt;code&gt;itsdangerous&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por otro lado, integré Stripe Checkout para permitir la activación de cuentas premium durante 24 horas. Esto implicó gestionar sesiones de pago, validaciones y control de acceso premium desde el backend, simulando una arquitectura muy cercana a aplicaciones SaaS reales.&lt;/p&gt;

&lt;p&gt;También trabajé especialmente en la organización modular del backend, separando autenticación, base de datos, servicios de email y clientes API en distintos módulos para mantener una estructura limpia y escalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resultado final
&lt;/h2&gt;

&lt;p&gt;El resultado fue una plataforma web completamente funcional orientada a contratación especializada en ciberseguridad.&lt;/p&gt;

&lt;p&gt;🔗 Web desplegada:&lt;br&gt;
&lt;a href="https://pablodiescj-dot.github.io/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;RedRecruit Online&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 Repositorio GitHub:&lt;br&gt;
&lt;a href="https://github.com/pablodiescj-dot/Proyecto-Master-Ciberseguridad-Evolve-PabloDiazHernandez?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Proyecto RedRecruit en GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Características destacadas del resultado final:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arquitectura modular&lt;/li&gt;
&lt;li&gt;Sistema premium funcional&lt;/li&gt;
&lt;li&gt;Integración de APIs externas&lt;/li&gt;
&lt;li&gt;Seguridad en autenticación&lt;/li&gt;
&lt;li&gt;Gestión de usuarios&lt;/li&gt;
&lt;li&gt;Diseño profesional y responsive&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lo que aprendí
&lt;/h2&gt;

&lt;p&gt;Este proyecto me permitió combinar desarrollo backend, seguridad web, autenticación, APIs externas y pagos online dentro de una misma aplicación completa.&lt;/p&gt;

&lt;p&gt;Además de mejorar mis habilidades con Flask y Python, aprendí cómo estructurar aplicaciones web más cercanas a un entorno profesional y cómo integrar servicios externos de forma segura y mantenible.&lt;/p&gt;

&lt;p&gt;También entendí mejor la importancia de la experiencia de usuario y de construir proyectos no solo funcionales, sino también presentables y preparados para producción.&lt;/p&gt;

&lt;p&gt;Proyecto académico desarrollado durante el Master en Ciberseguridad de Evolve.&lt;/p&gt;

&lt;p&gt;Si quieres ver el código completo o probar la plataforma, puedes visitar tanto el repositorio como la demo online.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>python</category>
      <category>flask</category>
      <category>stripe</category>
    </item>
    <item>
      <title>ESP32 GARDEN</title>
      <dc:creator>Darío Rosindo</dc:creator>
      <pubDate>Mon, 18 May 2026 10:11:43 +0000</pubDate>
      <link>https://dev.to/evolve-space/esp32-garden-2m5k</link>
      <guid>https://dev.to/evolve-space/esp32-garden-2m5k</guid>
      <description>&lt;h1&gt;
  
  
  Construyendo ESP32 Garden: Un Sistema IoT de Monitorización Agrícola de Extremo a Extremo
&lt;/h1&gt;

&lt;p&gt;La gestión botánica eficaz requiere una monitorización ambiental precisa. Depender de suposiciones para los horarios de riego o las condiciones ambientales a menudo conduce a una salud subóptima de las plantas. Para solucionar esto, desarrollé &lt;strong&gt;ESP32 Garden&lt;/strong&gt;, un sistema IoT de monitorización agrícola de extremo a extremo.&lt;/p&gt;

&lt;p&gt;Este proyecto captura datos ambientales en tiempo real utilizando sensores de hardware, los procesa a través de una arquitectura de microservicios personalizada en Python y visualiza los datos históricos en un panel web interactivo . Además, use una carcasa impresa en 3D para proteger los microcontroladores de la exposición a la tierra y la humedad.&lt;/p&gt;

&lt;p&gt;A continuación, se detalla la arquitectura del sistema, los componentes de hardware y el stack de software utilizados para dar vida a este proyecto.&lt;/p&gt;

&lt;h2&gt;
  
  
  La Arquitectura de Hardware
&lt;/h2&gt;

&lt;p&gt;El sistema utiliza un microcontrolador &lt;strong&gt;ESP32&lt;/strong&gt;, seleccionado principalmente por sus capacidades Wi-Fi integradas y su decente potencia de procesamiento. Se interconecta con los siguientes componentes de hardware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sensor DHT11:&lt;/strong&gt; Captura la temperatura ambiente y la humedad relativa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensor Analógico de Humedad del Suelo:&lt;/strong&gt; Mide el contenido volumétrico de agua en la tierra.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensor de Lluvia / Gotas:&lt;/strong&gt; Detecta eventos de precipitación.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pantalla OLED (SSD1306):&lt;/strong&gt; Proporciona depuración y lectura de estado en tiempo real en el propio dispositivo, sin necesidad de acceder al panel web.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Diseñando la Carcasa
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqxev9vx4do2ncwbc08e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqxev9vx4do2ncwbc08e.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desplegar componentes electrónicos expuestos en un entorno agrícola introduce riesgos significativos de cortocircuitos debido al agua y la suciedad. Para mitigar esto,imprimí en 3D una carcasa personalizada. Diseñada para parecerse a una pequeña casa, esta cubierta aloja de forma segura el ESP32 y el cableado, dejando solo las sondas de los sensores necesarias expuestas al entorno.&lt;/p&gt;

&lt;h2&gt;
  
  
  El Stack de Software
&lt;/h2&gt;

&lt;p&gt;La infraestructura de software es modular, dividiendo las responsabilidades entre el firmware integrado, una interfaz gráfica de gestión de escritorio, la ingesta de datos en segundo plano y la visualización frontend.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. El Firmware: C++,Arduino
&lt;/h3&gt;

&lt;p&gt;El ESP32 actúa como un dispositivo de borde (&lt;em&gt;edge device&lt;/em&gt;) ejecutando un servidor web ligero. En lugar de renderizar una página HTML pesada en el microcontrolador, expone una API REST a través del endpoint &lt;code&gt;/json&lt;/code&gt;. Cuando se le consulta, construye y devuelve las lecturas actuales de los sensores en un payload JSON estructurado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handleJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;temperatura&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperatura&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;humedad_amb&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;humedadAmb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;suelo&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;porcSuelo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;lluvia&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;porcLluvia&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Servicio de Ingesta de Datos
&lt;/h3&gt;

&lt;p&gt;Para registrar los datos a lo largo del tiempo, un script de Python actúa como un demonio en segundo plano. Envía peticiones HTTP periódicamente a la dirección IP del ESP32, analiza los datos JSON entrantes, añade una marca de tiempo y registra la entrada en un archivo CSV local utilizando &lt;code&gt;pandas&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;nueva_fila&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fecha_hora&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y-%m-%d %H:%M:%S&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temperatura&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temperatura&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;humedad_amb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;humedad_amb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;suelo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;suelo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lluvia&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lluvia&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;nueva_fila&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSV&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLUMNAS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CSV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLUMNAS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error de red: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Panel de Visualización de Datos
&lt;/h3&gt;

&lt;p&gt;Los datos en bruto requieren interpretación. Utilicé &lt;code&gt;streamlit&lt;/code&gt; y &lt;code&gt;plotly&lt;/code&gt; para desarrollar una aplicación web que lee el archivo CSV compilado y renderiza gráficos interactivos de series temporales. Esto permite un análisis detallado de tendencias, como monitorizar la tasa exacta de agotamiento de la humedad del suelo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamlit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;plotly.express&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;

&lt;span class="c1"&gt;# Renderizar gráficos interactivos con Plotly
&lt;/span&gt;&lt;span class="n"&gt;col_left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col_right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;col_left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fig_suelo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_filtrado&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fecha_hora&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;suelo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                        &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Humedad del Suelo (%)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;color_discrete_sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#7D4F39&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plotly_chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fig_suelo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_container_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**Media de humedad (Suelo):** &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;df_filtrado&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;suelo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;%&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;col_right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fig_hum_amb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;px&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_filtrado&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fecha_hora&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;humedad_amb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                          &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Humedad Ambiental (%)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;color_discrete_sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;#0077B6&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plotly_chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fig_hum_amb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_container_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Gestor de Configuración (main.py)
&lt;/h3&gt;

&lt;p&gt;Para agilizar el despliegue y gestionar los microservicios, el proyecto incluye un panel de control construido con &lt;code&gt;tkinter&lt;/code&gt;. Esta GUI permite al usuario monitorizar el estado de red del ESP32 en un hilo en segundo plano y alternar los servicios de captura de datos y del panel web mediante subprocesos (&lt;em&gt;subprocesses&lt;/em&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monitorear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ip_esp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lbl_status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ONLINE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;green&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lbl_status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OFFLINE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;red&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  El Montaje Final en Acción
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foj0smv2r117dtdh3cm78.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foj0smv2r117dtdh3cm78.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94dc5ivk6hoybarb5sma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94dc5ivk6hoybarb5sma.png" alt=" " width="392" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27v96rjnxtjeihb75fmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27v96rjnxtjeihb75fmd.png" alt=" " width="800" height="712"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Código Abierto y Replicación
&lt;/h2&gt;

&lt;p&gt;Este proyecto acorta la brecha entre los sistemas integrados de bajo nivel y los frameworks de ciencia de datos de alto nivel. Sirve como una base altamente escalable para cualquiera que busque adentrarse en el espacio del IoT.&lt;/p&gt;

&lt;p&gt;Todo el proyecto es de código abierto. Puedes revisar la arquitectura completa, acceder al firmware y encontrar instrucciones detalladas de configuración en mi repositorio de GitHub:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ros1ndoo/ESP32Garden" rel="noopener noreferrer"&gt;ros1ndoo/ESP32Garden en GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pasos para el Despliegue:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clona el repositorio e instala las dependencias.&lt;/li&gt;
&lt;li&gt;Conecta los sensores DHT11, de humedad del suelo y de lluvia a los pines GPIO designados del ESP32.&lt;/li&gt;
&lt;li&gt;Actualiza el archivo &lt;code&gt;settup.txt&lt;/code&gt; con las credenciales de tu red local.&lt;/li&gt;
&lt;li&gt;Ejecuta &lt;code&gt;main.py&lt;/code&gt;, haz clic en "Aplicar" para generar las cabeceras de C++ y flashea el ESP32.&lt;/li&gt;
&lt;li&gt;Utiliza la interfaz de Tkinter para inicializar el servicio de captura de datos y lanzar el panel de &lt;code&gt;streamlit&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>iot</category>
      <category>datascience</category>
      <category>esp32</category>
      <category>python</category>
    </item>
    <item>
      <title>De Data-Chaos a Data-Driven Decisions: Pipeline ETL Automatizado en Microsoft Fabric y PowerBI</title>
      <dc:creator>María Monedero</dc:creator>
      <pubDate>Sun, 17 May 2026 19:31:47 +0000</pubDate>
      <link>https://dev.to/evolve-space/de-data-chaos-a-data-driven-decisions-pipeline-etl-automatizado-en-microsoft-fabric-y-powerbi-3ce3</link>
      <guid>https://dev.to/evolve-space/de-data-chaos-a-data-driven-decisions-pipeline-etl-automatizado-en-microsoft-fabric-y-powerbi-3ce3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Dicen que lo más difícil de detectar es aquello que tenemos delante constantemente.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Las grandes organizaciones generan millones de datos cada día, pero disponer de información, no siempre significa comprenderla. Muchos datos permanecen aislados, dispersos o infrautilizados, dificultando la identificación de patrones, riesgos y oportunidades estratégicas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Porque un dato informa, pero millones, transforman&lt;/strong&gt;. Bajo esta idea nace &lt;strong&gt;ORIONTECH&lt;/strong&gt;, un proyecto académico basado en un pipeline analítico end-to-end desarrollado con Microsoft Fabric y Power BI, orientado al reporting ejecutivo, control financiero y monitorización operacional.&lt;/p&gt;

&lt;p&gt;El proyecto implementa una &lt;strong&gt;arquitectura Medallion&lt;/strong&gt; (Bronze, Silver y Gold) capaz de transformar datos raw en información estratégica mediante procesos automatizados de ingestión, limpieza, modelado y visualización. A través de PySpark Notebooks, Lakehouse y modelos analíticos en Power BI, ORIONTECH permite centralizar KPIs financieros, riesgos operacionales, desviaciones presupuestarias y métricas de productividad dentro de una misma plataforma diseñada con enfoque enterprise.&lt;/p&gt;

&lt;p&gt;Actualmente, la solución trabaja sobre un &lt;strong&gt;dataset&lt;/strong&gt; sintético inspirado en estructuras financieras y operacionales reales de mi entorno profesional, ya que la utilización de información corporativa real no es posible por motivos de confidencialidad y protección de datos.&lt;/p&gt;

&lt;p&gt;El dataset incluye aproximadamente 30.000 registros con variables relacionadas con ingresos, costes operativos, presupuestos, forecast financiero, productividad, departamentos y regiones internacionales.&lt;/p&gt;

&lt;p&gt;Uno de los &lt;strong&gt;principales retos&lt;/strong&gt; fue garantizar la consistencia y calidad del dato, ya que existían categorías duplicadas, nomenclaturas inconsistentes, valores nulos y diferencias de formato entre variables numéricas y textuales. Para resolverlo, fue necesario construir procesos de limpieza y estandarización dentro de la capa Silver antes de modelar la información para su consumo analítico en Power BI.&lt;/p&gt;

&lt;p&gt;Sobre este modelo se desarrollaron distintos dashboards orientados a diferentes perspectivas del negocio: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Executive Overview&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0jffvyzeob4vfuwpz75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0jffvyzeob4vfuwpz75.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;2. Operational Risk&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovtph4yha27nqwit5cyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovtph4yha27nqwit5cyn.png" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;3. Financial Performance&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jsvl0nzpyatfdfovznz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jsvl0nzpyatfdfovznz.png" alt=" " width="800" height="441"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;4. Controlling Report&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb8zew5u5tfqsg6l9350.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb8zew5u5tfqsg6l9350.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uno de los aspectos más interesantes del proyecto fue comprobar cómo determinados departamentos concentraban gran parte de los costes ocultos y de la exposición al riesgo operacional, impactando directamente sobre la rentabilidad global de la organización. &lt;/p&gt;

&lt;p&gt;Como evolución futura, ORIONTECH podrá incorporar comparaciones en los KPIS vs budget y vs forecast; implementar el análisis predictivo y la monitorización en tiempo real mediante inteligencia artificial. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Este proyecto ha sido diseñado con un enfoque escalable y orientado a su posible implantación en entornos corporativos reales, permitiendo automatizar procesos repetitivos, optimizar el reporting ejecutivo y fomentar una cultura data-driven dentro de las distintas áreas de negocio.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Github Repository: &lt;a href="https://github.com/evolve-space/Proyecto-Master-DataScience-Evolve-MariaMonedero.git" rel="noopener noreferrer"&gt;https://github.com/evolve-space/Proyecto-Master-DataScience-Evolve-MariaMonedero.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Proyecto desarrollado durante el Máster en Data Science &amp;amp; Artificial Intelligence de Evolve: &lt;a href="https://evolve.es/" rel="noopener noreferrer"&gt;https://evolve.es/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>fabric</category>
      <category>powerbi</category>
    </item>
    <item>
      <title>Explorando el éxito musical en Spotify con Python</title>
      <dc:creator>Maria Angeles Ciobanu</dc:creator>
      <pubDate>Sun, 17 May 2026 14:37:58 +0000</pubDate>
      <link>https://dev.to/evolve-space/explorando-el-exito-musical-en-spotify-con-python-185e</link>
      <guid>https://dev.to/evolve-space/explorando-el-exito-musical-en-spotify-con-python-185e</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ddk7fsx1jy5cej4x573.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ddk7fsx1jy5cej4x573.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explorando el éxito musical en Spotify con Python&lt;/p&gt;

&lt;p&gt;En este proyecto realicé un análisis exploratorio de datos utilizando Python, Pandas y técnicas de visualización sobre un dataset de Spotify obtenido desde Kaggle.&lt;/p&gt;

&lt;p&gt;El objetivo principal fue analizar diferentes características musicales y estudiar su relación con la popularidad de las canciones dentro de Spotify.&lt;/p&gt;

&lt;p&gt;Tecnologías utilizadas&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Pandas&lt;/li&gt;
&lt;li&gt;NumPy&lt;/li&gt;
&lt;li&gt;Matplotlib&lt;/li&gt;
&lt;li&gt;Jupyter Notebook&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Análisis realizado&lt;/p&gt;

&lt;p&gt;Durante el proyecto se realizaron diferentes procesos de análisis exploratorio de datos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploración del dataset&lt;/li&gt;
&lt;li&gt;Análisis de valores nulos&lt;/li&gt;
&lt;li&gt;Visualización de datos&lt;/li&gt;
&lt;li&gt;Análisis de géneros musicales&lt;/li&gt;
&lt;li&gt;Correlaciones entre variables&lt;/li&gt;
&lt;li&gt;Clasificación de canciones según popularidad&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resultados&lt;/p&gt;

&lt;p&gt;El análisis permitió identificar diferentes patrones relacionados con la popularidad musical. Algunas variables como la danceability y la energía mostraron cierta relación con el éxito de las canciones dentro del dataset.&lt;/p&gt;

&lt;p&gt;Además, los gráficos y visualizaciones facilitaron la comprensión de las características musicales presentes en Spotify.&lt;/p&gt;

&lt;p&gt;Aprendizajes&lt;/p&gt;

&lt;p&gt;Este proyecto me permitió reforzar conocimientos relacionados con Python, manipulación de datos, visualización y análisis exploratorio utilizando herramientas fundamentales dentro de Data Science.&lt;/p&gt;

&lt;p&gt;GitHub Repository&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MariaAngelesCiobanu/Master-DataScience-Evolve-MariaAngelesCiobanu.git" rel="noopener noreferrer"&gt;https://github.com/MariaAngelesCiobanu/Master-DataScience-Evolve-MariaAngelesCiobanu.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Proyecto académico desarrollado durante el Máster en Data Science de Evolve.&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>pandas</category>
      <category>jupyter</category>
    </item>
    <item>
      <title>Customer Review Analysis with NLP: Sentiment Analysis and Topic Modeling using Python</title>
      <dc:creator>ivanmartiolme</dc:creator>
      <pubDate>Sun, 17 May 2026 13:44:41 +0000</pubDate>
      <link>https://dev.to/evolve-space/customer-review-analysis-with-nlp-sentiment-analysis-and-topic-modeling-using-python-2mim</link>
      <guid>https://dev.to/evolve-space/customer-review-analysis-with-nlp-sentiment-analysis-and-topic-modeling-using-python-2mim</guid>
      <description>&lt;h1&gt;
  
  
  Customer Review Analysis with NLP: Sentiment Analysis and Topic Modeling using Python
&lt;/h1&gt;

&lt;p&gt;Customer reviews contain valuable information about user satisfaction, service quality, and business performance. However, manually analyzing thousands of reviews is inefficient and often impossible at scale.&lt;/p&gt;

&lt;p&gt;In this project, I developed a Natural Language Processing (NLP) pipeline to automatically analyze customer reviews and extract actionable business insights from unstructured text data.&lt;/p&gt;

&lt;p&gt;The full project repository is available here:&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ivanmartiolme/Proyecto-Master-DataScience-Evolve-IvanMartinez" rel="noopener noreferrer"&gt;https://github.com/ivanmartiolme/Proyecto-Master-DataScience-Evolve-IvanMartinez&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Objectives
&lt;/h2&gt;

&lt;p&gt;The main goals of this project were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean and preprocess customer review text&lt;/li&gt;
&lt;li&gt;Perform sentiment analysis to classify reviews as positive or negative&lt;/li&gt;
&lt;li&gt;Identify recurring discussion topics automatically&lt;/li&gt;
&lt;li&gt;Analyze sentiment by topic&lt;/li&gt;
&lt;li&gt;Generate business insights from textual data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools and Technologies
&lt;/h2&gt;

&lt;p&gt;The project was developed using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;Pandas&lt;/li&gt;
&lt;li&gt;NumPy&lt;/li&gt;
&lt;li&gt;Scikit-learn&lt;/li&gt;
&lt;li&gt;Transformers (Hugging Face)&lt;/li&gt;
&lt;li&gt;Datasets (Hugging Face)&lt;/li&gt;
&lt;li&gt;Matplotlib&lt;/li&gt;
&lt;li&gt;Jupyter Notebook&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Data Collection and Preparation
&lt;/h3&gt;

&lt;p&gt;Customer reviews were loaded into a structured DataFrame for analysis. A full text preprocessing pipeline was applied, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lowercasing&lt;/li&gt;
&lt;li&gt;URL removal&lt;/li&gt;
&lt;li&gt;Punctuation and number removal&lt;/li&gt;
&lt;li&gt;Whitespace normalization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensured better model performance and cleaner topic extraction.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sentiment Analysis
&lt;/h3&gt;

&lt;p&gt;A pretrained Transformer-based sentiment analysis model was used to classify each review as positive or negative.&lt;/p&gt;

&lt;p&gt;This allowed measurement of overall customer satisfaction and helped identify problematic areas.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Topic Modeling
&lt;/h3&gt;

&lt;p&gt;To uncover the most frequent themes discussed by customers, TF-IDF vectorization and Non-negative Matrix Factorization (NMF) were applied.&lt;/p&gt;

&lt;p&gt;This revealed recurring topics such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Airport parking and transportation&lt;/li&gt;
&lt;li&gt;Customer service experience&lt;/li&gt;
&lt;li&gt;Pricing and additional fees&lt;/li&gt;
&lt;li&gt;Refund and cancellation issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Insight Generation
&lt;/h3&gt;

&lt;p&gt;Combining sentiment analysis with topic modeling made it possible to detect which topics generated the most negative feedback and where service improvements could be prioritized.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;p&gt;This project demonstrated how NLP techniques can transform large volumes of unstructured customer feedback into meaningful business intelligence.&lt;/p&gt;

&lt;p&gt;It also reinforced practical skills in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text preprocessing&lt;/li&gt;
&lt;li&gt;Transformer-based sentiment analysis&lt;/li&gt;
&lt;li&gt;Topic modeling&lt;/li&gt;
&lt;li&gt;Data storytelling&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Customer review analysis using NLP can significantly improve decision-making and customer experience strategies.&lt;/p&gt;

&lt;p&gt;This project was developed as part of the Master in Data Science at Evolve.&lt;/p&gt;

&lt;p&gt;Proyect web:&lt;br&gt;
&lt;a href="https://ivanmartiolme.github.io/Proyecto-Master-DataScience-Evolve-IvanMartinez/" rel="noopener noreferrer"&gt;https://ivanmartiolme.github.io/Proyecto-Master-DataScience-Evolve-IvanMartinez/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Linkedin:&lt;br&gt;
&lt;a href="https://www.linkedin.com/pulse/an%C3%A1lisis-de-rese%C3%B1as-clientes-con-nlp-sentimiento-y-martinez-olmedo-rutae/" rel="noopener noreferrer"&gt;https://www.linkedin.com/pulse/an%C3%A1lisis-de-rese%C3%B1as-clientes-con-nlp-sentimiento-y-martinez-olmedo-rutae/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Portfolio:&lt;br&gt;
&lt;a href="https://ivanmartiolme.github.io/" rel="noopener noreferrer"&gt;https://ivanmartiolme.github.io/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>nlp</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Cómo construí un sistema RAG para convertirme en Red Teamer con IA — proyecto en Evolve</title>
      <dc:creator>Alejandro Congil Sainz</dc:creator>
      <pubDate>Sat, 16 May 2026 20:59:06 +0000</pubDate>
      <link>https://dev.to/evolve-space/como-construi-un-sistema-rag-para-convertirme-en-red-teamer-con-ia-proyecto-en-evolve-4b2m</link>
      <guid>https://dev.to/evolve-space/como-construi-un-sistema-rag-para-convertirme-en-red-teamer-con-ia-proyecto-en-evolve-4b2m</guid>
      <description>&lt;p&gt;Llevo meses trabajando en algo que empezó como una necesidad práctica&lt;br&gt;
y se ha convertido en la base de mi estrategia para entrar en el mundo&lt;br&gt;
del Red Team: un sistema RAG personal que indexa todo mi conocimiento&lt;br&gt;
de ciberseguridad y lo hace consultable con lenguaje natural.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema que quería resolver
&lt;/h2&gt;

&lt;p&gt;Las sesiones del Máster generan una cantidad brutal de material:&lt;br&gt;
clases grabadas, ejercicios, apuntes, herramientas, frameworks...&lt;br&gt;
Todo disperso, todo difícil de recuperar en el momento que lo necesitas.&lt;br&gt;
Cuando estás en medio de un CTF o analizando un vector de ataque,&lt;br&gt;
no puedes permitirte buscar durante 20 minutos en carpetas.&lt;/p&gt;

&lt;p&gt;Quería un sistema que funcionara como un analista interno:&lt;br&gt;
&lt;em&gt;"¿Cómo se hace enumeración de subdominios con Amass?"&lt;/em&gt;&lt;br&gt;
Y que te devolviera el fragmento exacto de la clase donde se explica,&lt;br&gt;
más el contexto relevante.&lt;/p&gt;

&lt;h2&gt;
  
  
  El entorno y los datos
&lt;/h2&gt;

&lt;p&gt;La fuente principal son las sesiones del Máster en Ciberseguridad de Evolve:&lt;br&gt;
22 sesiones grabadas en MP4, apuntes en PDF y ejercicios prácticos.&lt;/p&gt;

&lt;p&gt;El desafío principal era el vídeo: horas de audio técnico denso que&lt;br&gt;
necesitaban ser transcritas, fragmentadas y vectorizadas sin perder&lt;br&gt;
el contexto de cada concepto.&lt;/p&gt;

&lt;p&gt;Estado actual del sistema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;4.146 fragmentos&lt;/strong&gt; indexados en ChromaDB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;22 sesiones&lt;/strong&gt; de clase procesadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1.169 herramientas OSINT&lt;/strong&gt; catalogadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;33 categorías&lt;/strong&gt; de técnicas de ataque&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  El proceso
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;1. Ingesta de vídeo&lt;/em&gt;&lt;br&gt;
Cada MP4 pasa por &lt;code&gt;ffmpeg&lt;/code&gt; para extraer el audio, luego Whisper&lt;br&gt;
(OpenAI) lo transcribe. El texto resultante se divide en chunks&lt;br&gt;
con solapamiento para no perder contexto entre fragmentos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Embeddings y base vectorial&lt;/strong&gt;&lt;br&gt;
Los chunks se vectorizan con &lt;code&gt;sentence-transformers&lt;/code&gt; y se almacenan&lt;br&gt;
en ChromaDB. Cada fragmento mantiene metadatos: fuente, timestamp,&lt;br&gt;
categoría temática.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Motor RAG&lt;/strong&gt;&lt;br&gt;
La consulta del usuario se vectoriza y se recuperan los K fragmentos&lt;br&gt;
más similares. Claude API (Anthropic) recibe esos fragmentos como&lt;br&gt;
contexto y genera una respuesta fundamentada en el material real del curso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Interfaces&lt;/strong&gt;&lt;br&gt;
Construí tres interfaces para casos de uso distintos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chat web&lt;/strong&gt; (Streamlit): consultas en lenguaje natural&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OSINT Lab&lt;/strong&gt;: búsqueda semántica sobre 1.169 herramientas catalogadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework Tracker&lt;/strong&gt;: seguimiento de técnicas por fase del ataque&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resultados
&lt;/h2&gt;

&lt;p&gt;El sistema recupera el fragmento correcto con precisión alta incluso&lt;br&gt;
con consultas vagas o en lenguaje coloquial. La diferencia respecto&lt;br&gt;
a una búsqueda por keywords es notable: el RAG entiende contexto,&lt;br&gt;
no solo palabras.&lt;/p&gt;

&lt;p&gt;Lo más valioso: puedo hacer preguntas compuestas tipo&lt;br&gt;
&lt;em&gt;"¿Qué diferencia hay entre la enumeración pasiva y activa según&lt;br&gt;
lo visto en clase, y qué herramientas recomienda el profesor para cada fase?"&lt;/em&gt;&lt;br&gt;
y el sistema cruza información de múltiples sesiones en una respuesta coherente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que aprendí
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El chunking es más crítico de lo que parece. Chunks demasiado cortos
pierden contexto; demasiado largos diluyen la relevancia.&lt;/li&gt;
&lt;li&gt;Whisper comete errores en términos técnicos específicos (nombres de
herramientas, flags de comandos). Añadí un paso de post-procesado
con diccionario de correcciones.&lt;/li&gt;
&lt;li&gt;La elección del modelo de embeddings afecta mucho la calidad de
recuperación en dominio técnico especializado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El siguiente paso es expandir el sistema hacia las fases de explotación&lt;br&gt;
y post-explotación, completando el roadmap Red Team que tengo definido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ecosistema del proyecto
&lt;/h2&gt;

&lt;p&gt;Este artículo forma parte de un ecosistema interconectado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portfolio: &lt;a href="https://alexc-projects.github.io/Proyecto-Master-Ciberseguridad-Evolve-AlejandroCongil" rel="noopener noreferrer"&gt;https://alexc-projects.github.io/Proyecto-Master-Ciberseguridad-Evolve-AlejandroCongil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/Alexc-projects/Proyecto-Master-Ciberseguridad-Evolve-AlejandroCongil" rel="noopener noreferrer"&gt;https://github.com/Alexc-projects/Proyecto-Master-Ciberseguridad-Evolve-AlejandroCongil&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/pulse/de-las-telecomunicaciones-al-red-team-c%C3%B3mo-uso-ia-mi-congil-sainz-z6h4e/" rel="noopener noreferrer"&gt;https://www.linkedin.com/pulse/de-las-telecomunicaciones-al-red-team-cómo-uso-ia-mi-congil-sainz-z6h4e/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Medium: &lt;a href="https://medium.com/@alejandro.congil5/de-t%C3%A9cnico-de-redes-a-red-teamer-la-ia-como-ventaja-competitiva-en-ciberseguridad-68975e56dd7d" rel="noopener noreferrer"&gt;https://medium.com/@alejandro.congil5/de-técnico-de-redes-a-red-teamer-la-ia-como-ventaja-competitiva-en-ciberseguridad-68975e56dd7d&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Proyecto desarrollado durante el &lt;strong&gt;Máster en Ciberseguridad de &lt;a href="https://evolve.es" rel="noopener noreferrer"&gt;Evolve&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>security</category>
    </item>
  </channel>
</rss>
