In diesem Tutorial zeigen wir, wie man über statische, codelastige Diagramme hinausgeht und direkt mit ihnen einen wirklich interaktiven Workflow für die explorative Datenanalyse erstellt PyGWalker. Wir beginnen mit der Vorbereitung des Titanic-Datensatzes für umfangreiche interaktive Abfragen. Diese analysebereiten technischen Funktionen offenbaren die zugrunde liegende Struktur der Daten und ermöglichen gleichzeitig sowohl eine detaillierte Untersuchung auf Zeilenebene als auch aggregierte Ansichten auf hoher Ebene für tiefere Einblicke. Die Einbettung einer Drag-and-Drop-Schnittstelle im Tableau-Stil direkt in das Pocket book ermöglicht schnelle Hypothesentests, intuitive Kohortenvergleiche und eine effiziente Datenqualitätsprüfung, und das alles ohne die Reibung, die durch den Wechsel zwischen Code- und Visualisierungstools entsteht.

import sys, subprocess, json, math, os
from pathlib import Path


def pip_install(pkgs):
   subprocess.check_call((sys.executable, "-m", "pip", "set up", "-q") + pkgs)


pip_install((
   "pygwalker>=0.4.9",
   "duckdb>=0.10.0",
   "pandas>=2.0.0",
   "numpy>=1.24.0",
   "seaborn>=0.13.0"
))


import numpy as np
import pandas as pd
import seaborn as sns


df_raw = sns.load_dataset("titanic").copy()
print("Uncooked form:", df_raw.form)
show(df_raw.head(3))

Wir richten eine saubere und reproduzierbare Colab-Umgebung ein, indem wir alle erforderlichen Abhängigkeiten für interaktives EDA installieren. Wir laden den Titanic-Datensatz und führen eine erste Plausibilitätsprüfung durch, um seine Rohstruktur und seinen Umfang zu verstehen. Es schafft eine stabile Grundlage, bevor eine Transformation oder Visualisierung beginnt.

def make_safe_bucket(collection, bins=None, labels=None, q=None, prefix="bucket"):
   s = pd.to_numeric(collection, errors="coerce")
   if q will not be None:
       attempt:
           cuts = pd.qcut(s, q=q, duplicates="drop")
           return cuts.astype("string").fillna("Unknown")
       besides Exception:
           cross
   if bins will not be None:
       cuts = pd.reduce(s, bins=bins, labels=labels, include_lowest=True)
       return cuts.astype("string").fillna("Unknown")
   return s.astype("float64")


def preprocess_titanic_advanced(df):
   out = df.copy()
   out.columns = (c.strip().decrease().change(" ", "_") for c in out.columns)


   for c in ("survived", "pclass", "sibsp", "parch"):
       if c in out.columns:
           out(c) = pd.to_numeric(out(c), errors="coerce").fillna(-1).astype("int64")


   if "age" in out.columns:
       out("age") = pd.to_numeric(out("age"), errors="coerce").astype("float64")
       out("age_is_missing") = out("age").isna()
       out("age_bucket") = make_safe_bucket(
           out("age"),
           bins=(0, 12, 18, 30, 45, 60, 120),
           labels=("little one", "teen", "young_adult", "grownup", "mid_age", "senior"),
       )


   if "fare" in out.columns:
       out("fare") = pd.to_numeric(out("fare"), errors="coerce").astype("float64")
       out("fare_is_missing") = out("fare").isna()
       out("log_fare") = np.log1p(out("fare").fillna(0))
       out("fare_bucket") = make_safe_bucket(out("fare"), q=8)


   for c in ("intercourse", "class", "who", "embarked", "alone", "adult_male"):
       if c in out.columns:
           out(c) = out(c).astype("string").fillna("Unknown")


   if "cabin" in out.columns:
       out("deck") = out("cabin").astype("string").str.strip().str(0).fillna("Unknown")
       out("deck_is_missing") = out("cabin").isna()
   else:
       out("deck") = "Unknown"
       out("deck_is_missing") = True


   if "ticket" in out.columns:
       t = out("ticket").astype("string")
       out("ticket_len") = t.str.len().fillna(0).astype("int64")
       out("ticket_has_alpha") = t.str.accommodates(r"(A-Za-z)", regex=True, na=False)
       out("ticket_prefix") = t.str.extract(r"^((A-Za-z./s)+)", broaden=False).fillna("None").str.strip()
       out("ticket_prefix") = out("ticket_prefix").change("", "None").astype("string")


   if "sibsp" in out.columns and "parch" in out.columns:
       out("family_size") = (out("sibsp") + out("parch") + 1).astype("int64")
       out("is_alone") = (out("family_size") == 1)


   if "title" in out.columns:
       title = out("title").astype("string").str.extract(r",s*((^.)+).", broaden=False).fillna("Unknown").str.strip()
       vc = title.value_counts(dropna=False)
       preserve = set(vc(vc >= 15).index.tolist())
       out("title") = title.the place(title.isin(preserve), different="Uncommon").astype("string")
   else:
       out("title") = "Unknown"


   out("phase") = (
       out("intercourse").fillna("Unknown").astype("string")
       + " | "
       + out("class").fillna("Unknown").astype("string")
       + " | "
       + out("age_bucket").fillna("Unknown").astype("string")
   )


   for c in out.columns:
       if out(c).dtype == bool:
           out(c) = out(c).astype("int64")
       if out(c).dtype == "object":
           out(c) = out(c).astype("string")


   return out


df = preprocess_titanic_advanced(df_raw)
print("Prepped form:", df.form)
show(df.head(3))

Wir konzentrieren uns auf fortschrittliche Vorverarbeitung und Characteristic-Engineering, um die Rohdaten in eine analysebereite Kind umzuwandeln. Wir erstellen robuste, DuckDB-sichere Funktionen wie Buckets, Segmente und konstruierte kategoriale Signale, die die nachgelagerte Exploration verbessern. Wir stellen sicher, dass der Datensatz stabil, ausdrucksstark und für interaktive Abfragen geeignet ist.

def data_quality_report(df):
   rows = ()
   n = len(df)
   for c in df.columns:
       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)
       pattern = s.dropna().head(3).tolist()
       rows.append({
           "col": c,
           "dtype": dtype,
           "lacking": miss,
           "missing_%": spherical(miss_pct, 2),
           "nunique": nunique,
           "sample_values": pattern
       })
   return pd.DataFrame(rows).sort_values(("lacking", "nunique"), ascending=(False, False))


dq = data_quality_report(df)
show(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.pattern(MAX_ROWS_FOR_UI, random_state=RANDOM_SEED).reset_index(drop=True)


agg = (
   df.groupby(("phase", "deck", "embarked"), dropna=False)
     .agg(
         n=("survived", "measurement"),
         survival_rate=("survived", "imply"),
         avg_fare=("fare", "imply"),
         avg_age=("age", "imply"),
     )
     .reset_index()
)


for c in ("survival_rate", "avg_fare", "avg_age"):
   agg(c) = agg(c).astype("float64")


Path("/content material").mkdir(mother and father=True, exist_ok=True)
df_for_ui.to_csv("/content material/titanic_prepped_for_ui.csv", index=False)
agg.to_csv("/content material/titanic_agg_segment_deck_embarked.csv", index=False)

Wir bewerten die Datenqualität und erstellen einen strukturierten Überblick über Fehlen, Kardinalität und Datentypen. Wir bereiten sowohl einen Datensatz auf Zeilenebene als auch eine aggregierte Tabelle auf Kohortenebene vor, um eine schnelle Vergleichsanalyse zu unterstützen. Die duale Darstellung ermöglicht es uns, gleichzeitig detaillierte Muster und übergeordnete Traits zu untersuchen.

import pygwalker as pyg


SPEC_PATH = Path("/content material/pygwalker_spec_titanic.json")


def load_spec(path):
   if path.exists():
       attempt:
           return json.hundreds(path.read_text())
       besides Exception:
           return None
   return None


def save_spec(path, spec_obj):
   attempt:
       if isinstance(spec_obj, str):
           spec_obj = json.hundreds(spec_obj)
       path.write_text(json.dumps(spec_obj, indent=2))
       return True
   besides Exception:
       return False


def launch_pygwalker(df, spec_path):
   spec = load_spec(spec_path)
   kwargs = {}
   if spec will not be None:
       kwargs("spec") = spec


   attempt:
       walker = pyg.stroll(df, use_kernel_calc=True, **kwargs)
   besides TypeError:
       walker = pyg.stroll(df, **kwargs) if spec will not be None else pyg.stroll(df)


   captured = None
   for attr in ("spec", "_spec"):
       if hasattr(walker, attr):
           attempt:
               captured = getattr(walker, attr)
               break
           besides Exception:
               cross
   for meth in ("to_spec", "export_spec", "get_spec"):
       if captured is None and hasattr(walker, meth):
           attempt:
               captured = getattr(walker, meth)()
               break
           besides Exception:
               cross


   if captured will not be None:
       save_spec(spec_path, captured)


   return walker


walker_rows = launch_pygwalker(df_for_ui, SPEC_PATH)
walker_agg = pyg.stroll(agg)

Wir integrieren PyGWalker, um unsere vorbereiteten Tabellen in eine vollständig interaktive Drag-and-Drop-Analyseschnittstelle umzuwandeln. Wir behalten die Visualisierungsspezifikation bei, sodass Dashboard-Layouts und Codierungen auch Pocket book-Wiederholungen überdauern. Es verwandelt das Pocket book in eine wiederverwendbare Erkundungsumgebung im BI-Stil.

HTML_PATH = Path("/content material/pygwalker_titanic_dashboard.html")


def export_html_best_effort(df, spec_path, out_path):
   spec = load_spec(spec_path)
   html = None


   attempt:
       html = pyg.stroll(df, spec=spec, return_html=True) if spec will not be None else pyg.stroll(df, return_html=True)
   besides Exception:
       html = None


   if html is None:
       for fn in ("to_html", "export_html"):
           if hasattr(pyg, fn):
               attempt:
                   f = getattr(pyg, fn)
                   html = f(df, spec=spec) if spec will not be None else f(df)
                   break
               besides Exception:
                   proceed


   if html is None:
       return None


   if not isinstance(html, str):
       html = str(html)


   out_path.write_text(html, encoding="utf-8")
   return out_path


export_html_best_effort(df_for_ui, SPEC_PATH, HTML_PATH)

Wir erweitern den Workflow, indem wir das interaktive Dashboard als eigenständiges HTML-Artefakt exportieren. Wir stellen sicher, dass die Analyse geteilt oder überprüft werden kann, ohne dass eine Python-Umgebung oder eine Colab-Sitzung erforderlich ist. Es vervollständigt die Pipeline von Rohdaten bis hin zu verteilbaren, interaktiven Erkenntnissen.

Interaktives EDA-Dashboard

Zusammenfassend haben wir ein robustes Muster für fortgeschrittene EDA erstellt, das weit über den Titanic-Datensatz hinaus skaliert und gleichzeitig vollständig Pocket book-nativ bleibt. Wir haben gezeigt, wie sorgfältige Vorverarbeitung, Typsicherheit und Characteristic-Design es PyGWalker ermöglichen, zuverlässig mit komplexen Daten zu arbeiten, und wie die Kombination detaillierter Datensätze mit aggregierten Zusammenfassungen leistungsstarke analytische Arbeitsabläufe ermöglicht. Anstatt die Visualisierung als nachträglichen Gedanken zu behandeln, nutzten wir sie als erstklassige interaktive Ebene, die es uns ermöglichte, Annahmen zu iterieren, zu validieren und Erkenntnisse in Echtzeit zu gewinnen.


Schauen Sie sich das an Vollständige Codes hier. Sie können uns auch gerne weiter folgen Twitter und vergessen Sie nicht, bei uns mitzumachen 100.000+ ML SubReddit und Abonnieren Unser Publication. Warten! Bist du im Telegram? Jetzt können Sie uns auch per Telegram kontaktieren.


Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert