Marcel0123 commited on
Commit
2b5f33e
·
verified ·
1 Parent(s): a6312f0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -64
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py Titanic Data Adventure (wit thema, verhalend, centrale afbeelding, interactieve overlevingskans)
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
@@ -59,10 +59,10 @@ def train_model(dfx: pd.DataFrame):
59
  acc = model.score(X_test, y_test)
60
  return model, acc
61
 
62
- model, model_acc = train_model(df)
63
 
64
  # =========================
65
- # Plots (duidelijk en informatief)
66
  # =========================
67
  def make_plot(fig, title):
68
  fig.update_layout(
@@ -127,7 +127,7 @@ def predict_and_story(pclass, sex, age, sibsp, parch, fare, embarked):
127
  family_size = int(sibsp) + int(parch) + 1
128
 
129
  X_row = [[int(pclass), sex_enc, float(age), int(sibsp), int(parch), float(fare), embarked_enc, family_size]]
130
- prob = float(model.predict_proba(X_row)[0,1])
131
  pct = prob * 100
132
 
133
  # Avontuur-tekst op basis van invoer en kans
@@ -164,19 +164,76 @@ Je voelt de houten reling koud onder je hand. {ending}
164
  return story
165
 
166
  # =========================
167
- # UI (vast lay-out, wit thema, veel uitleg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  # =========================
169
  CUSTOM_CSS = """
170
  body { background: #FFFFFF; color: #0B1C3F; }
171
  .gradio-container { background: #FFFFFF; }
172
  h1, h2, h3, h4 { color: #1B4B91; }
173
- .intro-card, .section {
174
  background: #F9FBFF;
175
  border: 1px solid #E0E6F3;
176
  border-radius: 12px;
177
  padding: 16px;
178
  }
179
- .subtitle { color: #4F6FA9; }
180
  .hero-img img { border-radius: 12px; border: 1px solid #E0E6F3; }
181
  .kpi {
182
  display:flex; flex-direction:column; align-items:center; justify-content:center;
@@ -184,60 +241,39 @@ h1, h2, h3, h4 { color: #1B4B91; }
184
  }
185
  .kpi .value { font-size:1.6rem; font-weight:800; color:#1B4B91; }
186
  .kpi .label { font-size:.9rem; color:#3F557A; }
 
187
  """
188
 
189
  with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as demo:
190
- # Titel
191
- gr.Markdown("# 🛳️ Titanic Data Adventure")
192
- gr.Markdown(
193
- "<p class='subtitle' style='text-align:center;'>"
194
- "Een verhalende ontdekkingstocht door data, besluitvorming en overlevingskansen."
195
- "</p>"
196
- )
197
-
198
- # Intro: afbeelding + verhaal
199
  with gr.Row():
200
- with gr.Column(scale=1, min_width=320):
201
- gr.HTML("<div class='intro-card'><h3>📖 Proloog</h3>"
202
- "<p>April 1912. De RMS Titanic verlaat Europa richting New York. "
203
- "We kijken mee door de lens van data: wie stapten aan boord? "
204
- "Wie overleefden – en waarom?</p>"
205
- "<p>Links zie je een historisch beeld van het schip (jouw geüploade afbeelding). "
206
- "Rechts nemen we je mee langs inzichten en uiteindelijk jouw persoonlijke scenario.</p></div>")
207
  with gr.Column(scale=1, min_width=320):
208
  if HERO_PATH:
209
- hero = gr.Image(value=HERO_PATH, interactive=False, show_label=False, elem_classes=["hero-img"])
210
  else:
211
- gr.Markdown("⚠️ **Geen afbeelding gevonden.** Plaats `titanic_bg.png` óf `titanic_bg.jpg` in de root.")
212
 
213
- # Kerncijfers
214
  with gr.Row():
215
- k1 = gr.HTML(f"<div class='kpi'><div class='value'>{len(df):,}</div><div class='label'>Totaal passagiers</div></div>")
216
- k2 = gr.HTML(f"<div class='kpi'><div class='value'>{int(df['survived'].sum()):,}</div><div class='label'>Overlevenden</div></div>")
217
- k3 = gr.HTML(f"<div class='kpi'><div class='value'>{df['survived'].mean()*100:.1f}%</div><div class='label'>% Overleefd</div></div>")
218
- k4 = gr.HTML(f"<div class='kpi'><div class='value'>{', '.join(map(str, sorted(df['pclass'].unique())))}</div><div class='label'>Klassen</div></div>")
219
-
220
- # Hoofdstuk 1: Wie zaten er aan boord?
221
- with gr.Column(elem_classes=["section"]):
222
- gr.Markdown("## Hoofdstuk 1 — Wie zaten er aan boord?")
223
- gr.Markdown(
224
- "We beginnen bij de samenstelling van de passagiers: klasse, leeftijd en geslacht. "
225
- "Historisch gezien zijn dit belangrijke factoren voor kansen op redding."
226
- )
227
- with gr.Row():
228
- g1 = gr.Plot(label="Overleving per klasse")
229
- g2 = gr.Plot(label="Leeftijdsverdeling per status")
230
- with gr.Row():
231
- g3 = gr.Plot(label="Geslachtsverdeling")
232
- g4 = gr.Plot(label="Ticketprijs per klasse")
233
-
234
- # Hoofdstuk 2: Jouw scenario – interactieve kans + verhaal
235
- with gr.Column(elem_classes=["section"]):
236
- gr.Markdown("## Hoofdstuk 2 — Stel jezelf voor...")
237
- gr.Markdown(
238
- "Voer jouw gegevens in. We gebruiken een getraind model (Random Forest) om je overlevingskans te schatten "
239
- "én we vertellen jouw verhaal — een korte scène op het dek."
240
- )
241
  with gr.Row():
242
  ui_pclass = gr.Slider(1, 3, value=2, step=1, label="Klasse (1=1e, 3=3e)")
243
  ui_sex = gr.Radio(["Man","Vrouw"], value="Man", label="Geslacht")
@@ -247,20 +283,9 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as d
247
  ui_parch = gr.Slider(0, 6, value=0, step=1, label="Ouders/Kinder(en) aan boord")
248
  ui_fare = gr.Slider(0, 600, value=50, label="Ticketprijs (£)")
249
  ui_emb = gr.Radio(["C","Q","S"], value="S", label="Vertrekhaven")
250
- btn = gr.Button("🎲 Bereken én vertel mijn verhaal")
251
  story_out = gr.Markdown()
252
 
253
- # Hoofdstuk 3: Hoe lezen we deze grafieken?
254
- with gr.Column(elem_classes=["section"]):
255
- gr.Markdown("## Hoofdstuk 3 — Wat leren we hieruit?")
256
- gr.Markdown(
257
- "- **Klasse** maakt een groot verschil: reddingsboten waren beter bereikbaar voor de 1e klasse.\n"
258
- "- **Vrouwen en kinderen** kregen vaak voorrang, wat zichtbaar is in de verdeling naar geslacht.\n"
259
- "- **Leeftijd** en **familiegrootte** spelen mee: jonge gezinnen hadden andere kansen en keuzes.\n"
260
- "- **Ticketprijs** (fare) en **klasse** hangen sterk samen, en correleren indirect met overleving.\n\n"
261
- "Let op: een model is een benadering van de historische patronen. Achter elke datapunt schuilt een persoonlijk verhaal."
262
- )
263
-
264
  # callbacks
265
  def load_graphs():
266
  return (
 
1
+ # app.py Titanic Data Adventure (wit thema, vaste layout, uitgebreide intro naast foto)
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
 
59
  acc = model.score(X_test, y_test)
60
  return model, acc
61
 
62
+ MODEL, MODEL_ACC = train_model(df)
63
 
64
  # =========================
65
+ # Plots (licht, informatief)
66
  # =========================
67
  def make_plot(fig, title):
68
  fig.update_layout(
 
127
  family_size = int(sibsp) + int(parch) + 1
128
 
129
  X_row = [[int(pclass), sex_enc, float(age), int(sibsp), int(parch), float(fare), embarked_enc, family_size]]
130
+ prob = float(MODEL.predict_proba(X_row)[0,1])
131
  pct = prob * 100
132
 
133
  # Avontuur-tekst op basis van invoer en kans
 
164
  return story
165
 
166
  # =========================
167
+ # Introductietekst (uitgebreid, modern paneel)
168
+ # =========================
169
+ INTRO_MD = """
170
+ # 🛳️ Titanic Data Adventure
171
+ ### Een datagedreven reis door hoop, hiërarchie en toeval
172
+
173
+ **April 1912.**
174
+ De RMS *Titanic* vertrekt richting New York: een drijvend paleis, gevuld met verwachtingen. Aan boord: industriëlen in avondkleding, jonge gezinnen met één koffer, bemanningsleden die elke dag routine tot ritueel verheffen. De zee is kalm; de toekomst lijkt maakbaar.
175
+
176
+ Meer dan een eeuw later kijken wij mee — niet met verrekijkers of logboeken, maar met **data**. Elk record in deze dataset is een menselijk verhaal: iemand met een plek aan tafel, een ticket, een familie, een keuze. Door de gegevens te verkennen, begrijpen we beter **wie overleefde — en waarom**.
177
+
178
+ ---
179
+
180
+ ## Waarom deze data ertoe doet
181
+ - **Patronen ontrafelen**: cijfers tonen structuur in chaos — welke groepen hadden toegang tot reddingsboten, wie bevond zich waar, en wat betekende dat?
182
+ - **Mens achter het datapunt**: elke rij is iemands dag, iemands kans, iemands lot.
183
+ - **Leren van geschiedenis**: ongelijkheid, beslissingen en beperkte middelen — thema’s die vandaag nog steeds resoneren.
184
+
185
+ ---
186
+
187
+ ## Wat je in dit dashboard gaat zien
188
+ 1. **Kerncijfers** – Hoeveel passagiers, hoeveel overlevenden, en hoe die verdeeld waren over de **klassen**.
189
+ 2. **Verdelingen** – Leeftijd, geslacht, ticketprijs (*fare*), familieomvang.
190
+ 3. **Verbanden** – Overleving t.o.v. klasse en geslacht; prijsverschillen per klasse; samenhang tussen variabelen.
191
+ 4. **Machine learning** – Een model dat, op basis van historische patronen, jouw **persoonlijke overlevingskans** inschat.
192
+ 5. **Jouw scenario** – Voer je kenmerken in en lees een korte scene die je terugplaatst op het dek, die nacht.
193
+
194
+ ---
195
+
196
+ ## De sociologie van de dekken
197
+ - **Klasse** was letterlijk een **fysieke laag** aan boord: 1e klasse hoger en centraler, 3e klasse dieper in het schip.
198
+ - **Toegang** tot informatie, bemanning en reddingsmiddelen verschilde per dek.
199
+ - **Normen & regels** (“**women and children first**”) werden niet overal gelijk toegepast; context en chaos bepaalden veel.
200
+
201
+ ---
202
+
203
+ ## Hoe lees je de grafieken?
204
+ - **Overleving per klasse**: staafdiagram dat laat zien hoe kans ongelijk verdeeld was.
205
+ - **Leeftijdsverdeling**: overlappende histogrammen; kijk waar de bulten liggen voor *Overleefd* vs. *Niet overleefd*.
206
+ - **Geslachtsverdeling**: cirkelgrafiek; benadrukt het effect van sociale normen.
207
+ - **Fare per klasse**: boxplot; toont spreiding en uitschieters — rijkdom was geen garantie, maar wel een voordeel.
208
+
209
+ ---
210
+
211
+ ## Wat een model wél en niet doet
212
+ - ✅ **Herkennen van patronen**: het model leert uit combinaties (bijv. *geslacht + klasse + leeftijd*).
213
+ - ✅ **Schatten, geen zekerheid**: het geeft **kansen**, geen waarheden.
214
+ - ❌ **Geen moreel oordeel**: data verklaart, maar rechtvaardigt niet.
215
+ - ❌ **Geen individuele lotsbeschikking**: context die niet in data staat (locatie op het moment, gedrag van omstanders) blijft onzichtbaar.
216
+
217
+ ---
218
+
219
+ ### Klaar om te beginnen?
220
+ Scroll door de grafieken, lees de toelichtingen en voer je eigen kenmerken in.
221
+ Het model berekent je **overlevingskans** en we schetsen een **scène** uit die nacht — zodat data weer mens wordt.
222
+ """
223
+
224
+ # =========================
225
+ # UI (vast lay-out, wit thema)
226
  # =========================
227
  CUSTOM_CSS = """
228
  body { background: #FFFFFF; color: #0B1C3F; }
229
  .gradio-container { background: #FFFFFF; }
230
  h1, h2, h3, h4 { color: #1B4B91; }
231
+ .panel, .intro-card {
232
  background: #F9FBFF;
233
  border: 1px solid #E0E6F3;
234
  border-radius: 12px;
235
  padding: 16px;
236
  }
 
237
  .hero-img img { border-radius: 12px; border: 1px solid #E0E6F3; }
238
  .kpi {
239
  display:flex; flex-direction:column; align-items:center; justify-content:center;
 
241
  }
242
  .kpi .value { font-size:1.6rem; font-weight:800; color:#1B4B91; }
243
  .kpi .label { font-size:.9rem; color:#3F557A; }
244
+ .scroll-md { max-height: 520px; overflow-y: auto; padding-right: 8px; }
245
  """
246
 
247
  with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as demo:
248
+ # Intro: lange tekst (links) + foto (rechts)
 
 
 
 
 
 
 
 
249
  with gr.Row():
250
+ with gr.Column(scale=2, min_width=420):
251
+ gr.Markdown(INTRO_MD, elem_classes=["intro-card","scroll-md"])
 
 
 
 
 
252
  with gr.Column(scale=1, min_width=320):
253
  if HERO_PATH:
254
+ gr.Image(value=HERO_PATH, interactive=False, show_label=False, elem_classes=["hero-img"])
255
  else:
256
+ gr.Markdown("⚠️ **Geen afbeelding gevonden.** Plaats `titanic_bg.png` of `titanic_bg.jpg` in de root.")
257
 
258
+ # KPI's
259
  with gr.Row():
260
+ gr.HTML(f"<div class='kpi'><div class='value'>{len(df):,}</div><div class='label'>Totaal passagiers</div></div>")
261
+ gr.HTML(f"<div class='kpi'><div class='value'>{int(df['survived'].sum()):,}</div><div class='label'>Overlevenden</div></div>")
262
+ gr.HTML(f"<div class='kpi'><div class='value'>{df['survived'].mean()*100:.1f}%</div><div class='label'>% Overleefd</div></div>")
263
+ gr.HTML(f"<div class='kpi'><div class='value'>{', '.join(map(str, sorted(df['pclass'].unique())))}</div><div class='label'>Klassen</div></div>")
264
+
265
+ # Visualisaties
266
+ gr.Markdown("## 📊 Verken de data", elem_classes=["panel"])
267
+ with gr.Row():
268
+ g1 = gr.Plot(label="Overleving per klasse")
269
+ g2 = gr.Plot(label="Leeftijdsverdeling per status")
270
+ with gr.Row():
271
+ g3 = gr.Plot(label="Geslachtsverdeling")
272
+ g4 = gr.Plot(label="Ticketprijs per klasse")
273
+
274
+ # Interactieve voorspelling
275
+ with gr.Column(elem_classes=["panel"]):
276
+ gr.Markdown("## 🔮 Jouw scenario — bereken je overlevingskans en lees je scène")
 
 
 
 
 
 
 
 
 
277
  with gr.Row():
278
  ui_pclass = gr.Slider(1, 3, value=2, step=1, label="Klasse (1=1e, 3=3e)")
279
  ui_sex = gr.Radio(["Man","Vrouw"], value="Man", label="Geslacht")
 
283
  ui_parch = gr.Slider(0, 6, value=0, step=1, label="Ouders/Kinder(en) aan boord")
284
  ui_fare = gr.Slider(0, 600, value=50, label="Ticketprijs (£)")
285
  ui_emb = gr.Radio(["C","Q","S"], value="S", label="Vertrekhaven")
286
+ btn = gr.Button("🎲 Bereken én vertel mijn verhaal", variant="primary")
287
  story_out = gr.Markdown()
288
 
 
 
 
 
 
 
 
 
 
 
 
289
  # callbacks
290
  def load_graphs():
291
  return (