En este tutorial, demostramos cómo ir más allá de los gráficos estáticos y con mucho código y crear un flujo de trabajo de análisis de datos exploratorios genuinamente interactivo directamente usando PyGWalker. Comenzamos preparando el conjunto de datos del Titanic para consultas interactivas a gran escala. Estas funciones de ingeniería listas para el análisis revelan la estructura subyacente de los datos y al mismo tiempo permiten una exploración detallada a nivel de fila y vistas agregadas de alto nivel para obtener una visión más profunda. La incorporación de una interfaz de arrastrar y soltar estilo Tableau directamente en el portátil permite realizar pruebas rápidas de hipótesis, comparaciones de cohortes intuitivas y una inspección eficiente de la calidad de los datos, todo sin la fricción de cambiar entre el código y las herramientas de visualización.
“pygwalker>=0.4.9”,
“duckdb>=0.10.0”,
“pandas>=2.0.0”,
“numpy>=1.24.0”,
“seaborn>=0.13.0”
]) importar numpy como np importar pandas como pd importar seaborn como sns df_raw = sns.load_dataset(“titanic”).copy() print(“Raw shape:”, df_raw.shape) display(df_raw.head(3))
Configuramos un entorno Colab limpio y reproducible instalando todas las dependencias necesarias para EDA interactivo. Cargamos el conjunto de datos del Titanic y realizamos una verificación inicial de cordura para comprender su estructura y escala sin procesar. Establece una base estable antes de que comience cualquier transformación o visualización.
para c en [“survived”, “pclass”, “sibsp”, “parch”]: si c dentro fuera.columnas: fuera[c] = pd.to_numeric(fuera[c]errores=”coerce”).fillna(-1).astype(“int64”) si “edad” en out.columns: out[“age”] = pd.to_numeric(fuera[“age”]errores=”coerce”).astype(“float64”) fuera[“age_is_missing”] = fuera[“age”].isna() fuera[“age_bucket”] = make_safe_bucket( fuera[“age”]contenedores =[0, 12, 18, 30, 45, 60, 120]etiquetas =[“child”, “teen”, “young_adult”, “adult”, “mid_age”, “senior”]) si “tarifa” en out.columns: out[“fare”] = pd.to_numeric(fuera[“fare”]errores=”coerce”).astype(“float64”) fuera[“fare_is_missing”] = fuera[“fare”].isna() fuera[“log_fare”] = np.log1p(fuera[“fare”].fillna(0)) fuera[“fare_bucket”] = make_safe_bucket(fuera[“fare”]q=8) para c en [“sex”, “class”, “who”, “embarked”, “alone”, “adult_male”]: si c dentro fuera.columnas: fuera[c] = fuera[c].astype(“string”).fillna(“Unknown”) si “cabina” está en out.columns: out[“deck”] = fuera[“cabin”].astype(“cadena”).str.strip().str[0].fillna(“Desconocido”) fuera[“deck_is_missing”] = fuera[“cabin”].isna() más: fuera[“deck”] = “Desconocido” fuera[“deck_is_missing”] = Verdadero si “boleto” está en columnas de salida: t = salida[“ticket”].astype(“cadena”) fuera[“ticket_len”] = t.str.len().fillna(0).astype(“int64”) fuera[“ticket_has_alpha”] = t.str.contiene(r”[A-Za-z]”, expresión regular=Verdadero, na=Falso) fuera[“ticket_prefix”] = t.str.extract(r”^([A-Za-z\.\/\s]+)”, expand=False).fillna(“Ninguno”).str.strip() fuera[“ticket_prefix”] = fuera[“ticket_prefix”].replace(“”, “Ninguno”).astype(“string”) si “sibsp” en out.columns y “parch” en out.columns: out[“family_size”] = (fuera[“sibsp”] + fuera[“parch”] + 1).astype(“int64”) fuera[“is_alone”] = (fuera[“family_size”] == 1) si “nombre” está en out.columns: título = out[“name”].astype(“cadena”).str.extract(r”,\s*([^\.]+)\.”, expand=False).fillna(“Desconocido”).str.strip() vc = title.value_counts(dropna=False) keep = set(vc[vc >= 15].index.tolist()) fuera[“title”] = título.dónde(título.isin(mantener), otro=”Raro”).astype(“cadena”) else: fuera[“title”] = “Desconocido” fuera[“segment”] = (fuera[“sex”].fillna(“Desconocido”).astype(“cadena”) + ” | ” + salida[“class”].fillna(“Desconocido”).astype(“cadena”) + ” | ” + salida[“age_bucket”].fillna(“Unknown”).astype(“string”) ) para c en out.columns: si está fuera[c].dtype == bool: fuera[c] = fuera[c].astype(“int64”) si está fuera[c].dtype == “objeto”: fuera[c] = fuera[c].astype(“string”) devuelve df = preprocess_titanic_advanced(df_raw) print(“Forma preparada:”, df.shape) display(df.head(3))
Nos centramos en el preprocesamiento avanzado y la ingeniería de funciones para convertir los datos sin procesar en un formato listo para el análisis. Creamos funciones sólidas y seguras para DuckDB, como depósitos, segmentos y señales categóricas diseñadas que mejoran la exploración posterior. Nos aseguramos de que el conjunto de datos sea estable, expresivo y adecuado para consultas interactivas.
n = len(df) para c en df.columnas: s = df[c]
miss = int(s.isna().sum()) miss_pct = (miss / n * 100.0) if n else 0.0 nunique = int(s.nunique(dropna=True)) dtype = str(s.dtype) sample = s.dropna().head(3).tolist() rows.append({ “col”: c, “dtype”: dtype, “missing”: miss, “missing_%”: round(miss_pct, 2), “nunique”: nunique, “sample_values”: muestra }) return pd.DataFrame(rows).sort_values([“missing”, “nunique”]ascendente =[False, False]) dq = data_quality_report(df) display(dq.head(20)) RANDOM_SEED = 42 MAX_ROWS_FOR_UI = 200_000 df_for_ui = df if len(df_for_ui) > MAX_ROWS_FOR_UI: df_for_ui = df_for_ui.sample(MAX_ROWS_FOR_UI, random_state=RANDOM_SEED).reset_index(drop=True) agg = ( df.groupby([“segment”, “deck”, “embarked”]dropna=False) .agg( n=(“sobrevivió”, “tamaño”), survival_rate=(“sobrevivió”, “media”), avg_fare=(“tarifa”, “media”), avg_age=(“edad”, “media”), ) .reset_index() ) para c en [“survival_rate”, “avg_fare”, “avg_age”]: ag[c] = agregar[c].astype(“float64”) Ruta(“/content”).mkdir(parents=True, exist_ok=True) df_for_ui.to_csv(“/content/titanic_prepped_for_ui.csv”, index=False) agg.to_csv(“/content/titanic_agg_segment_deck_embarked.csv”, index=False)
Evaluamos la calidad de los datos y generamos una descripción general estructurada de faltantes, cardinalidad y tipos de datos. Preparamos un conjunto de datos a nivel de fila y una tabla agregada a nivel de cohorte para respaldar un análisis comparativo rápido. La representación dual nos permite explorar patrones detallados y tendencias de alto nivel simultáneamente.
Integramos PyGWalker para transformar nuestras tablas preparadas en una interfaz analítica totalmente interactiva de arrastrar y soltar. Mantenemos la especificación de visualización para que los diseños y codificaciones del tablero sobrevivan a las reejecuciones del cuaderno. Convierte el portátil en un entorno de exploración reutilizable de estilo BI.
Ampliamos el flujo de trabajo exportando el panel interactivo como un artefacto HTML independiente. Nos aseguramos de que el análisis se pueda compartir o revisar sin necesidad de un entorno Python o una sesión de Colab. Completa el proceso desde datos sin procesar hasta información distribuible e interactiva.
En conclusión, establecimos un patrón sólido para EDA avanzado que va mucho más allá del conjunto de datos del Titanic sin dejar de ser completamente nativo de los portátiles. Mostramos cómo el preprocesamiento cuidadoso, la seguridad de tipos y el diseño de funciones permiten que PyGWalker opere de manera confiable con datos complejos y cómo la combinación de registros detallados con resúmenes agregados desbloquea poderosos flujos de trabajo analíticos. En lugar de tratar la visualización como una ocurrencia tardía, la utilizamos como una capa interactiva de primera clase, lo que nos permite iterar, validar suposiciones y extraer conocimientos en tiempo real.
Consulte los códigos completos aquí. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 100.000 ML y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.