Marcel0123 commited on
Commit
f9c2e0a
·
verified ·
1 Parent(s): cbd3079

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +22 -188
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py — Titanic Data Adventure (met uitgebreide introductie naast foto)
2
 
3
  import gradio as gr
4
  import pandas as pd
@@ -117,46 +117,25 @@ def train_and_embed_solid():
117
  return status, fig
118
 
119
  # ======================================================
120
- # TEKST VOOR INTRODUCTIE (UITGEBREID)
121
  # ======================================================
122
  INTRO_MD = """
123
- # 🛳️ Titanic Data Adventure
124
- ### Een datagedreven reis door hoop, hiërarchie en toeval
125
- **April 1912.**
126
- De RMS *Titanic* vertrekt richting New York: een drijvend paleis, gevuld met verwachtingen.
127
  Aan boord: industriëlen in avondkleding, jonge gezinnen met één koffer, bemanningsleden met routine.
128
- De zee is kalm; de toekomst lijkt maakbaar.
129
- Meer dan een eeuw later kijken wij mee — niet met verrekijkers of logboeken, maar met **data**.
130
  Elk record in deze dataset is een menselijk verhaal: iemand met een plek aan tafel, een ticket, een familie, een keuze.
131
- Door de gegevens te verkennen, begrijpen we beter **wie overleefde — en waarom**.
132
- ---
133
- ### ⚓ De nacht die geschiedenis werd
134
- Op **14 april 1912**, net voor middernacht, raakte de *Titanic* een **ijsberg** in de ijskoude Noord-Atlantische Oceaan.
135
- Binnen drie uur zonk het schip – het “onzinkbare” symbool van vooruitgang bleek kwetsbaar.
136
- Meer dan **1.500 mensen** kwamen om, slechts een derde van de opvarenden vond redding in de sloepen.
137
- De verdeling tussen rijk en arm, man en vrouw, jong en oud bleek letterlijk van levensbelang.
138
- In deze applicatie duiken we opnieuw die nacht in – niet met reddingsvesten, maar met grafieken, modellen en cijfers
139
- die het menselijk verhaal achter de ramp zichtbaar maken.
140
  """
141
 
142
- # ======================================================
143
- # UITLEGTEKST NAAST DE 2D-PLOT
144
- # ======================================================
145
  EXPLAIN_MD_SIDE = """
146
- ### 📘 Wat je ziet
147
- Bij het opstarten traint de computer een **RandomForest-model** dat leert wie op de Titanic **overleefde** – en waarom.
148
- Het kijkt naar **klasse**, **geslacht**, **leeftijd**, **familieomvang**, **ticketprijs** en **haven van vertrek**.
149
- De nauwkeurigheid (bijv. *74%*) betekent: in 74 van de 100 gevallen voorspelt het model correct.
150
- ---
151
- ### 🗺️ Landkaart van passagiers
152
- Elk **bolletje** is één persoon. Met **PCA** brengen we veel kenmerken terug naar **2 dimensies**.
153
- - **Blauw** → overleefd
154
- - **Grijs** → niet overleefd
155
- - **Vorm** → klasse
156
- Dichter bij elkaar = vergelijkbare profielen. **Hover** voor details.
157
- ---
158
- ### 💬 Jij in dit verhaal
159
- Vul onderaan je **eigen profiel** in, ontdek jouw kans en lees je scène uit die nacht.
160
  """
161
 
162
  # ======================================================
@@ -177,78 +156,6 @@ def plot_fare_box(dfx):
177
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
178
  return make_plot(f, "Ticketprijs per klasse (met overleving)")
179
 
180
- # ======================================================
181
- # INTERACTIEVE VOORSPELLING
182
- # ======================================================
183
- def predict_and_story(pclass, sex, age, sibsp, parch, fare, embarked):
184
- if MODEL is None:
185
- return "⏳ Het model initialiseert nog. Probeer het zo nog eens."
186
- X_row = pd.DataFrame([{
187
- "pclass": int(pclass), "sex": sex, "age": float(age),
188
- "sibsp": int(sibsp), "parch": int(parch), "fare": float(fare),
189
- "embarked": embarked, "family_size": int(sibsp)+int(parch)+1
190
- }])
191
- prob = float(MODEL.predict_proba(X_row)[0,1]); pct = prob*100
192
- klasse_txt = {1:"eerste",2:"tweede",3:"derde"}[int(pclass)]
193
- haven_txt = {"C":"Cherbourg","Q":"Queenstown","S":"Southampton"}[embarked]
194
- rol_txt = "vrouw" if sex.lower().startswith("v") else "man"
195
- if pct>=75:
196
- tone, ending = ("Je kansen zijn uitzonderlijk goed.",
197
- "Je bereikt de sloep; het schip helt achter je, maar je leeft.")
198
- elif pct>=50:
199
- tone, ending = ("Je kansen zijn behoorlijk goed.",
200
- "In de chaos vind je een plek in een halfgevulde sloep.")
201
- elif pct>=25:
202
- tone, ending = ("De kansen zijn fifty-fifty.",
203
- "Op het laatste moment spring je; de nacht is lang, maar de horizon gloeit.")
204
- else:
205
- tone, ending = ("Het ziet er somber uit.",
206
- "Je klampt je vast terwijl de oceaan meedogenloos wordt.")
207
- return f"""### 🔮 Jouw overlevingskans: **{pct:.1f}%**
208
- **Situatie:** {rol_txt}, **{klasse_txt} klasse**, inscheping **{haven_txt}** — leeftijd **{int(age)}**, familie **{int(sibsp)}+{int(parch)}** (totaal {int(sibsp)+int(parch)+1}), ticket **£{float(fare):.2f}**.
209
- **Analyse:** {tone} Het model weegt o.a. klasse, geslacht, leeftijd en familieomvang mee.
210
- **Avontuur:** De nacht is stil; fluiten, geroep, voetstappen. {ending}
211
- """
212
-
213
- # ======================================================
214
- # LIVE GAUGE VOOR JOUW SCENARIO (met kleurbanden + threshold)
215
- # ======================================================
216
- def live_viz(pclass, sex, age, sibsp, parch, fare, embarked):
217
- # Retourneer een gauge die live de kans toont (0–100%) met kleurbanden
218
- if MODEL is None:
219
- return make_plot(go.Figure(), "Jouw overlevingskans (live)")
220
- X_row = pd.DataFrame([{
221
- "pclass": int(pclass), "sex": sex, "age": float(age),
222
- "sibsp": int(sibsp), "parch": int(parch), "fare": float(fare),
223
- "embarked": embarked, "family_size": int(sibsp)+int(parch)+1
224
- }])
225
- prob = float(MODEL.predict_proba(X_row)[0,1]) * 100.0
226
-
227
- fig = go.Figure(go.Indicator(
228
- mode="gauge+number",
229
- value=prob,
230
- number={"suffix": "%", "valueformat": ".1f"},
231
- gauge={
232
- "axis": {"range": [0, 100]},
233
- "bar": {"thickness": 0.25},
234
- # Kleurbanden (0–25 rood, 25–50 oranje, 50–75 geel, 75–100 groen)
235
- "steps": [
236
- {"range": [0, 25], "color": "#FDECEC"},
237
- {"range": [25, 50], "color": "#FFF2E0"},
238
- {"range": [50, 75], "color": "#FFF9D6"},
239
- {"range": [75, 100], "color": "#E8F6EA"},
240
- ],
241
- # Threshold-lijn op actuele waarde
242
- "threshold": {
243
- "line": {"color": "#1B4B91", "width": 4},
244
- "thickness": 0.9,
245
- "value": prob
246
- },
247
- },
248
- title={"text": "Jouw overlevingskans (live)"}
249
- ))
250
- return make_plot(fig, "Jouw overlevingskans (live)")
251
-
252
  # ======================================================
253
  # UI + LAYOUT
254
  # ======================================================
@@ -258,37 +165,21 @@ body { background:#FFFFFF; color:#0B1C3F; }
258
  h1, h2, h3, h4 { color:#1B4B91; }
259
  .panel, .intro-card { background:#F9FBFF; border:1px solid #E0E6F3; border-radius:12px; padding:16px; }
260
  .hero-img img { border-radius:12px; border:1px solid #E0E6F3; }
261
- .kpi { display:flex; flex-direction:column; align-items:center; justify-content:center;
262
- background:#FFFFFF; border:1px solid #E0E6F3; border-radius:12px; padding:14px; }
263
- .kpi .value { font-size:1.6rem; font-weight:800; color:#1B4B91; }
264
- .kpi .label { font-size:.9rem; color:#3F557A; }
265
- .explain-card { background:#EAF0FF; border-radius:12px; padding:18px; border:1px solid #D5E0FA; }
266
  """
267
 
268
  with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as demo:
269
- # Header-intro + foto
270
  with gr.Row():
271
  with gr.Column(scale=2, min_width=420):
272
- gr.Markdown(INTRO_MD, elem_classes=["intro-card"])
273
  with gr.Column(scale=1, min_width=320):
274
  hp = hero_path()
275
- if hp: gr.Image(value=hp, interactive=False, show_label=False, elem_classes=["hero-img"])
276
- else: gr.Markdown("⚠️ **Geen afbeelding gevonden.** Plaats `titanic_bg.png` of `titanic_bg.jpg` in de root.")
 
 
277
 
278
- # NIEUW PANEEL: Passagierslijst (volledige dataset, scrollbaar)
279
- with gr.Column(elem_classes=["panel"]):
280
- gr.Markdown("## 👥 Passagierslijst — volledige dataset (scrollbaar)")
281
- gr.DataFrame(
282
- value=df, # volledige dataset
283
- wrap=True,
284
- interactive=False, # alleen-lezen
285
- label="Titanic-passagiers",
286
- max_height=320 # vaste hoogte -> scroll binnen de tabel
287
- )
288
- # Kleine spacer om overlap te voorkomen
289
  gr.Markdown("")
290
 
291
- # Panel: status + 2D-plot links en uitleg rechts
292
  with gr.Column(elem_classes=["panel"]):
293
  gr.Markdown("## 🔧 Initialisatie & Modeltraining")
294
  status_md = gr.Markdown("⏳ Initialiseren…")
@@ -296,16 +187,13 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as d
296
  with gr.Column(scale=2, min_width=420):
297
  train_plot = gr.Plot(label="2D-projectie — elk bolletje is een passagier")
298
  with gr.Column(scale=1, min_width=320):
299
- gr.Markdown(EXPLAIN_MD_SIDE, elem_classes=["explain-card"])
300
 
301
- # KPIs
302
  with gr.Row():
303
- gr.HTML(f"<div class='kpi'><div class='value'>{len(df):,}</div><div class='label'>Totaal passagiers</div></div>")
304
- gr.HTML(f"<div class='kpi'><div class='value'>{int(df['survived'].sum()):,}</div><div class='label'>Overlevenden</div></div>")
305
- gr.HTML(f"<div class='kpi'><div class='value'>{df['survived'].mean()*100:.1f}%</div><div class='label'>% Overleefd</div></div>")
306
- gr.HTML(f"<div class='kpi'><div class='value'>{', '.join(map(str, sorted(df['pclass'].unique())))}</div><div class='label'>Klassen</div></div>")
307
 
308
- # Overige visualisaties
309
  gr.Markdown("## 📊 Verken de data", elem_classes=["panel"])
310
  with gr.Row():
311
  g2 = gr.Plot(label="Leeftijdsverdeling per status")
@@ -313,61 +201,7 @@ with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as d
313
  with gr.Row():
314
  g4 = gr.Plot(label="Ticketprijs per klasse")
315
 
316
- # Interactieve voorspelling
317
- with gr.Column(elem_classes=["panel"]):
318
- # Tekstblok + gauge naast elkaar
319
- with gr.Row():
320
- with gr.Column(scale=2, min_width=420):
321
- gr.Markdown("""## 🔮 Jouw scenario — bereken je overlevingskans en lees je scène
322
- Hier kun je ontdekken **hoe groot jouw kans op overleving** zou zijn geweest aan boord van de *Titanic* — en meteen het **verhaal van jouw nacht** lezen.
323
- 1. **Kies je profiel**
324
- - **Klasse:** 1e, 2e of 3e klasse (je reiscomfort en dekpositie).
325
- - **Geslacht:** man of vrouw — dit had invloed op reddingsvoorrang.
326
- - **Leeftijd:** jouw leeftijd in jaren.
327
- - **Broers/zussen** en **ouders/kinderen**: hoeveel familieleden reisden met je mee.
328
- - **Ticketprijs (£):** hoe duur je passage was.
329
- - **Vertrekhaven:** Cherbourg (C), Queenstown (Q) of Southampton (S).
330
- 2. **Klik op de knop “🎲 Bereken én vertel mijn verhaal”**
331
- Het model schat jouw **overlevingskans** op basis van historische patronen.
332
- 3. **Lees je persoonlijke scène**
333
- Onder de knop verschijnt een korte beschrijving die je meeneemt naar die nacht —
334
- gebaseerd op jouw ingevulde profiel en de berekende kans.
335
- > 💡 *De voorspelling is een statistische schatting, geen oordeel.
336
- > Ze helpt je zien hoe factoren zoals klasse, geslacht en leeftijd destijds iemands lot konden bepalen.*""")
337
- with gr.Column(scale=1, min_width=320):
338
- viz_plot = gr.Plot(label="Jouw overlevingskans (live)")
339
-
340
- with gr.Row():
341
- ui_pclass = gr.Slider(1, 3, value=2, step=1, label="Klasse (1=1e, 3=3e)")
342
- ui_sex = gr.Radio(["Man","Vrouw"], value="Man", label="Geslacht")
343
- ui_age = gr.Slider(0, 80, value=30, label="Leeftijd")
344
- with gr.Row():
345
- ui_sibsp = gr.Slider(0, 8, value=1, step=1, label="Broers/Zussen aan boord")
346
- ui_parch = gr.Slider(0, 6, value=0, step=1, label="Ouders/Kinder(en) aan boord")
347
- ui_fare = gr.Slider(0, 600, value=50, label="Ticketprijs (£)")
348
- ui_emb = gr.Radio(["C","Q","S"], value="S", label="Vertrekhaven")
349
- btn = gr.Button("🎲 Bereken én vertel mijn verhaal", variant="primary")
350
- story_out = gr.Markdown()
351
-
352
- # Loads & acties
353
  demo.load(fn=train_and_embed_solid, inputs=[], outputs=[status_md, train_plot])
354
  demo.load(lambda: (plot_age_hist(df), plot_gender(df), plot_fare_box(df)), inputs=[], outputs=[g2, g3, g4])
355
 
356
- # Initiele gauge (na modeltraining): gebruik de default UI-waarden
357
- demo.load(lambda: live_viz(2, "Man", 30, 1, 0, 50, "S"), inputs=[], outputs=[viz_plot])
358
-
359
- # Live updates bij elke wijziging
360
- for comp in [ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb]:
361
- comp.change(live_viz,
362
- inputs=[ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb],
363
- outputs=viz_plot)
364
-
365
- # Ook updaten bij de knop
366
- btn.click(predict_and_story,
367
- inputs=[ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb],
368
- outputs=story_out)
369
- btn.click(live_viz,
370
- inputs=[ui_pclass, ui_sex, ui_age, ui_sibsp, ui_parch, ui_fare, ui_emb],
371
- outputs=viz_plot)
372
-
373
  demo.launch()
 
1
+ # app.py — Titanic Data Adventure (alleen blauwe tekst, zonder zwart/vetgedrukt)
2
 
3
  import gradio as gr
4
  import pandas as pd
 
117
  return status, fig
118
 
119
  # ======================================================
120
+ # TEKSTEN (alleen blauwe kleur, geen vet of zwart)
121
  # ======================================================
122
  INTRO_MD = """
123
+ <span style='color:#1B4B91'>
124
+ April 1912.
125
+ De RMS Titanic vertrekt richting New York: een drijvend paleis, gevuld met verwachtingen.
 
126
  Aan boord: industriëlen in avondkleding, jonge gezinnen met één koffer, bemanningsleden met routine.
127
+ De zee is kalm; de toekomst lijkt maakbaar. Meer dan een eeuw later kijken wij mee — niet met verrekijkers of logboeken, maar met data.
 
128
  Elk record in deze dataset is een menselijk verhaal: iemand met een plek aan tafel, een ticket, een familie, een keuze.
129
+ Door de gegevens te verkennen, begrijpen we beter wie overleefde — en waarom.
130
+ </span>
 
 
 
 
 
 
 
131
  """
132
 
 
 
 
133
  EXPLAIN_MD_SIDE = """
134
+ <span style='color:#1B4B91'>
135
+ Bij het opstarten traint de computer een RandomForest-model dat leert wie op de Titanic overleefde – en waarom.
136
+ Het kijkt naar klasse, geslacht, leeftijd, familieomvang, ticketprijs en haven van vertrek.
137
+ De nauwkeurigheid (bijv. 74%) betekent: in 74 van de 100 gevallen voorspelt het model correct.
138
+ </span>
 
 
 
 
 
 
 
 
 
139
  """
140
 
141
  # ======================================================
 
156
  color_discrete_map={"Overleefd":"#1B4B91","Niet overleefd":"#A3B1C6"})
157
  return make_plot(f, "Ticketprijs per klasse (met overleving)")
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  # ======================================================
160
  # UI + LAYOUT
161
  # ======================================================
 
165
  h1, h2, h3, h4 { color:#1B4B91; }
166
  .panel, .intro-card { background:#F9FBFF; border:1px solid #E0E6F3; border-radius:12px; padding:16px; }
167
  .hero-img img { border-radius:12px; border:1px solid #E0E6F3; }
 
 
 
 
 
168
  """
169
 
170
  with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Default(primary_hue="blue")) as demo:
 
171
  with gr.Row():
172
  with gr.Column(scale=2, min_width=420):
173
+ gr.Markdown(INTRO_MD, elem_classes=["intro-card"], unsafe_allow_html=True)
174
  with gr.Column(scale=1, min_width=320):
175
  hp = hero_path()
176
+ if hp:
177
+ gr.Image(value=hp, interactive=False, show_label=False, elem_classes=["hero-img"])
178
+ else:
179
+ gr.Markdown("⚠️ **Geen afbeelding gevonden.** Plaats `titanic_bg.png` of `titanic_bg.jpg` in de root.")
180
 
 
 
 
 
 
 
 
 
 
 
 
181
  gr.Markdown("")
182
 
 
183
  with gr.Column(elem_classes=["panel"]):
184
  gr.Markdown("## 🔧 Initialisatie & Modeltraining")
185
  status_md = gr.Markdown("⏳ Initialiseren…")
 
187
  with gr.Column(scale=2, min_width=420):
188
  train_plot = gr.Plot(label="2D-projectie — elk bolletje is een passagier")
189
  with gr.Column(scale=1, min_width=320):
190
+ gr.Markdown(EXPLAIN_MD_SIDE, elem_classes=["explain-card"], unsafe_allow_html=True)
191
 
 
192
  with gr.Row():
193
+ gr.HTML(f"<div style='color:#1B4B91;'><strong>Totaal passagiers:</strong> {len(df):,}</div>")
194
+ gr.HTML(f"<div style='color:#1B4B91;'><strong>Overlevenden:</strong> {int(df['survived'].sum()):,}</div>")
195
+ gr.HTML(f"<div style='color:#1B4B91;'><strong>Percentage overleefd:</strong> {df['survived'].mean()*100:.1f}%</div>")
 
196
 
 
197
  gr.Markdown("## 📊 Verken de data", elem_classes=["panel"])
198
  with gr.Row():
199
  g2 = gr.Plot(label="Leeftijdsverdeling per status")
 
201
  with gr.Row():
202
  g4 = gr.Plot(label="Ticketprijs per klasse")
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  demo.load(fn=train_and_embed_solid, inputs=[], outputs=[status_md, train_plot])
205
  demo.load(lambda: (plot_age_hist(df), plot_gender(df), plot_fare_box(df)), inputs=[], outputs=[g2, g3, g4])
206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  demo.launch()