-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEffektgroessen.html
More file actions
643 lines (597 loc) · 44.3 KB
/
Copy pathEffektgroessen.html
File metadata and controls
643 lines (597 loc) · 44.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
<!DOCTYPE html>
<html lang="de" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Effektgrößen — MethodsLab</title>
<script>(function(){var t=localStorage.getItem('ml-theme');if(t)document.documentElement.setAttribute('data-theme',t);})();</script>
<style>
@import url('https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,400&family=Fraunces:ital,opsz,wght@0,9..144,200;0,9..144,300;0,9..144,600;1,9..144,300;1,9..144,400&display=swap');
:root{
--bg:#f0ead8;--paper:#f8f3e8;--ink:#18130e;--ink2:#5a4f42;--ink3:#8a7f72;
--a1:#c94a2a;--a2:#2a6e8a;--a3:#5a8a2a;--a4:#7a3a8a;--a5:#b85c00;--a6:#0e7c7b;
--grid:#ddd5c5;--panel:#e8e0ce;--border:#c8bfaa;
--accent:var(--a2);--topbar-h:54px;
}
[data-theme="dark"]{
--bg:#0c0f14;--paper:#111520;--ink:#ece6d8;--ink2:#8a8070;--ink3:#857c68;
--a1:#e8614a;--a2:#4ab0d8;--a3:#80cb52;--a4:#c87ad8;--a5:#e07830;--a6:#2bc7c4;
--grid:#1e242e;--panel:#171d28;--border:#2a3040;
}
*{box-sizing:border-box;margin:0;padding:0}
html{font-size:18px}
body{background:var(--bg);color:var(--ink);font-family:'Fraunces',Georgia,serif;font-size:1rem;min-height:100vh}
#topbar{position:sticky;top:0;z-index:300;background:var(--paper);border-bottom:1px solid var(--grid);
padding:.6rem 1.2rem;display:flex;align-items:center;gap:.8rem}
#topbar h1{font-size:1.05rem;font-weight:300;letter-spacing:-.01em;flex:1}
#topbar h1 em{color:var(--accent);font-style:italic}
.tbtn{font-family:'DM Mono',monospace;font-size:.72rem;padding:.28rem .7rem;border:1.5px solid var(--border);
background:transparent;cursor:pointer;color:var(--ink2);transition:all .15s;letter-spacing:.04em}
.tbtn:hover{background:var(--ink);color:var(--bg)}
.tbtn-red{border-color:var(--a1)!important;color:var(--a1)!important}
.tbtn-red:hover{background:var(--a1)!important;color:var(--bg)!important}
#app{display:grid;grid-template-columns:272px 1fr;height:calc(100vh - var(--topbar-h));overflow:hidden}
#sidebar{overflow-y:scroll;height:100%;background:var(--paper);border-right:1px solid var(--grid);padding:1rem .9rem}
#sidebar::-webkit-scrollbar{width:5px}
#sidebar::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
#main{overflow-y:scroll;height:100%;padding:1.2rem 1.5rem 3rem}
.scard{background:var(--panel);border:1px solid var(--grid);padding:.75rem .85rem;margin-bottom:.7rem}
.scard-title{font-family:'DM Mono',monospace;font-size:.75rem;letter-spacing:.1em;text-transform:uppercase;
color:var(--accent);margin-bottom:.6rem;padding-bottom:.3rem;border-bottom:1px solid var(--grid)}
.mode-row{display:grid;grid-template-columns:1fr;gap:.4rem;margin-bottom:.2rem}
.mode-btn{font-family:'DM Mono',monospace;font-size:.75rem;padding:.4rem .5rem;border:1.5px solid var(--border);
background:transparent;cursor:pointer;color:var(--ink2);transition:all .15s;text-align:center}
.mode-btn:hover{border-color:var(--accent);color:var(--accent)}
.mode-btn.active{border-color:var(--accent);background:var(--accent);color:var(--bg)}
.sb-note{font-size:.78rem;line-height:1.65;color:var(--ink3);margin-top:.5rem}
.sec-h{font-family:'DM Mono',monospace;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;
color:var(--ink3);margin:1.6rem 0 .6rem;padding-bottom:.3rem;border-bottom:1px solid var(--grid)}
.sec-h:first-child{margin-top:0}
.p-intro{font-size:.92rem;line-height:1.85;color:var(--ink2);margin-bottom:.75rem}
.p-intro strong{color:var(--ink)}
.story-box{background:var(--panel);border:1px solid var(--grid);border-left:3px solid var(--a2);
padding:.8rem .95rem;margin-bottom:1.1rem;line-height:1.6;font-size:.95rem}
.story-lbl{font-family:'DM Mono',monospace;font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
color:var(--a2);margin-bottom:.45rem}
.story-box strong{color:var(--ink)} .story-box em{font-style:italic;color:var(--ink)}
.circ{font-size:1.5em;font-weight:600;vertical-align:-.13em;line-height:1;display:inline-block}
.slider-row{margin-bottom:.55rem}
.slider-lbl{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:.22rem}
.slider-name{font-family:'DM Mono',monospace;font-size:.78rem;color:var(--ink)}
.slider-val{font-family:'DM Mono',monospace;font-size:.82rem;color:var(--accent);font-weight:500}
input[type=range]{width:100%;appearance:none;height:3px;background:var(--grid);border-radius:2px;outline:none;cursor:pointer}
input[type=range]::-webkit-slider-thumb{appearance:none;width:12px;height:12px;background:var(--ink);border-radius:50%;cursor:pointer}
input[type=range]::-webkit-slider-thumb:hover{background:var(--accent)}
input[type=range]::-moz-range-thumb{width:12px;height:12px;background:var(--ink);border-radius:50%;cursor:pointer;border:none}
.canvas-wrap{background:var(--panel);border:1px solid var(--grid);margin-bottom:1.1rem;overflow:hidden}
.canvas-wrap canvas{width:100%;display:block}
.canvas-axis-note{font-family:'DM Mono',monospace;font-size:.72rem;color:var(--ink3);
padding:.5rem .85rem;border-top:1px solid var(--grid);line-height:1.5}
.results-section{margin-bottom:1rem}
.rs-head{font-family:'DM Mono',monospace;font-size:.73rem;letter-spacing:.1em;text-transform:uppercase;
color:var(--ink3);margin-bottom:.55rem;padding-bottom:.3rem;border-bottom:1px solid var(--grid)}
.d-table{width:100%;border-collapse:collapse;margin-bottom:.35rem;table-layout:auto}
.d-table th{font-family:'DM Mono',monospace;font-size:.68rem;letter-spacing:.07em;text-transform:uppercase;
color:var(--ink3);text-align:left;padding:.28rem .5rem;border-bottom:1px solid var(--grid);background:var(--panel);
white-space:nowrap}
.d-table th.num{text-align:right}
.d-table td{font-family:'DM Mono',monospace;font-size:.79rem;padding:.28rem .5rem;border-bottom:1px solid var(--grid);
background:var(--paper);vertical-align:middle;white-space:nowrap}
.d-table tr:last-child td{border-bottom:none}
.d-table td.num{text-align:right;color:var(--ink);font-weight:500}
.d-table td.lbl{color:var(--ink2)}
.step-block{margin-bottom:1.2rem}
.step-h{font-size:1rem;font-weight:300;margin-bottom:.35rem}
.step-body{font-size:.87rem;line-height:1.8;color:var(--ink2)}
.step-body strong{color:var(--ink)}
.learn-section{margin-top:2.2rem}
.lcard-grid{column-count:2;column-gap:.7rem}
.lcard{background:var(--paper);border:1.5px solid var(--border);padding:.9rem 1rem;
break-inside:avoid;margin-bottom:.7rem}
.lcard-h{font-family:'DM Mono',monospace;font-size:.72rem;color:var(--a2);
letter-spacing:.07em;text-transform:uppercase;margin-bottom:.4rem;font-weight:500}
.lcard-body{font-size:.82rem;line-height:1.75;color:var(--ink2)}
.lcard-body strong{color:var(--ink)}
.lcard-body a{color:var(--a2)}
.lcard.rechner{border-color:var(--a2);border-left-width:3px}
.help-overlay{display:none;position:fixed;inset:0;z-index:500;background:rgba(0,0,0,.82);overflow-y:auto;padding:2rem 1rem}
.help-overlay.open{display:block}
.help-panel{max-width:700px;margin:0 auto;background:var(--paper);border:1px solid var(--border);padding:2rem}
.help-panel h2{font-family:'Fraunces',serif;font-weight:300;font-size:1.2rem;margin-bottom:1.2rem}
.help-h3{font-family:'DM Mono',monospace;font-size:.74rem;letter-spacing:.09em;text-transform:uppercase;
color:var(--a1);margin:1.1rem 0 .35rem}
.help-p{font-size:.85rem;line-height:1.8;color:var(--ink2);margin-bottom:.6rem}
.help-p code{font-family:'DM Mono',monospace;font-size:.8rem;background:var(--panel);padding:.1rem .35rem;color:var(--ink)}
.help-p a{color:var(--a2)}
.help-close{font-family:'DM Mono',monospace;font-size:.74rem;padding:.3rem .8rem;
border:1.5px solid var(--a1);background:transparent;cursor:pointer;color:var(--a1);transition:all .15s}
.help-close:hover{background:var(--a1);color:var(--bg)}
</style>
</head>
<body>
<div id="topbar">
<h1>Effektgrößen — <em>verstehen & interpretieren</em></h1>
<span style="font-family:'DM Mono',monospace;font-size:.7rem;color:var(--ink3);white-space:nowrap">Dr. R. Düsing · Universität Osnabrück</span>
<button class="tbtn tbtn-red" onclick="toggleHelp()">? Hilfe</button>
<button class="tbtn" id="theme-btn" onclick="toggleTheme()">☀ Light</button>
</div>
<!-- HELP OVERLAY -->
<div class="help-overlay" id="help-overlay" onclick="if(event.target===this)toggleHelp()">
<div class="help-panel">
<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:1.3rem">
<h2>Hilfe — Effektgrößen</h2>
<button class="help-close" onclick="toggleHelp()">✕ Schließen</button>
</div>
<div class="help-h3">Was zeigt dieses Tool?</div>
<p class="help-p">Eine geführte Einführung in Effektgrößen für Mittelwertsvergleiche — anhand eines durchgehenden Beispiels, dessen Parameter per Slider verändert werden können. Für exakte Berechnungen mit eigenen Daten (CSV-Upload, Konfidenzintervalle nach Bonett/Rosenthal/NCT, alle Korrekturen) siehe den <a href="Effektgroessen_Rechner.html">Effektgrößen-Rechner</a>.</p>
<div class="help-h3">Das laufende Beispiel</div>
<p class="help-p">Eine Psychologin untersucht, ob ein 8-wöchiges Achtsamkeitstraining das Wohlbefinden steigert. <strong style="color:var(--ink)">Between:</strong> Trainingsgruppe vs. Warteliste-Kontrollgruppe, je n Personen. <strong style="color:var(--ink)">Within:</strong> dieselben Personen vor (Prä) und nach (Post) dem Training, mit Prä-Post-Korrelation r. Alle Mittelwerte, Streuungen, n (und r) sind frei einstellbar — die Zahlen im Beispiel sind ein plausibler Startpunkt, keine feste Vorgabe.</p>
<div class="help-h3">Was zeigt der Plot?</div>
<p class="help-p">Die beiden Kurven sind die <strong style="color:var(--ink)">angenommenen Populationsverteilungen</strong> der beiden Gruppen auf der tatsächlichen Messwert-Skala (x-Achse) — mit ihren jeweils eingestellten Mittelwerten und Streuungen. Eine schmalere, höhere Kurve hat eine kleinere Streuung; das ist keine Verzerrung, sondern korrekt: die Fläche unter jeder Kurve ist immer gleich groß (= 100% dieser Gruppe). Die <strong style="color:var(--ink)">grau schattierte Fläche</strong> ist der Bereich, in dem sich beide Verteilungen überschneiden — je mehr Überlappung, desto schwerer lässt sich anhand eines einzelnen Werts erkennen, aus welcher Gruppe eine Person stammt. Der <strong style="color:var(--ink)">Pfeil</strong> zeigt den rohen Mittelwertsunterschied auf der Originalskala; die Zahl <code>d</code> daneben ist derselbe Unterschied, standardisiert an einer Streuung (siehe unten) — deshalb ohne Einheit und über Studien hinweg vergleichbar.</p>
<div class="help-h3">Cohen's d im Detail</div>
<p class="help-p">d = (M₁ − M₂) / SD. Das Vorzeichen zeigt die Richtung (hier: positiv = Zunahme), der Betrag die Größe. Cohens (1988) informelle Konvention: |d| ≈ 0.2 klein, 0.5 mittel, 0.8 groß — als grobe Orientierung gedacht, nicht als feste Schwelle; die praktische Bedeutsamkeit hängt immer vom Feld und der Fragestellung ab.</p>
<div class="help-h3">Warum mehrere Standardisierungen bei Messwiederholung?</div>
<p class="help-p">Bei unabhängigen Gruppen gibt es einen naheliegenden Nenner: die gepoolte Streuung beider Gruppen. Bei Messwiederholung dagegen ist unklar, <em>wessen</em> Streuung standardisiert werden soll. Drei Konventionen haben sich etabliert:</p>
<p class="help-p"><code>d<sub>z</sub></code> — Differenzen-SD als Nenner; direkt nutzbar für t-Test-Power und CLES nach Wuensch.<br>
<code>d<sub>rm</sub></code> — d<sub>z</sub> · √(2(1−r)) (Becker 1988): gleich d<sub>av</sub> bei Varianzhomogenität, gleich d<sub>z</sub> bei r = .5.<br>
<code>d<sub>av</sub></code> — mittlere SD von Prä und Post als Nenner (Lakens 2013); kein r im Nenner.</p>
<p class="help-p">Die drei Werte fallen umso stärker auseinander, je höher die Prä-Post-Korrelation r ist — das lässt sich im Within-Modus direkt am Regler beobachten.</p>
<div class="help-h3">d_av und Vergleichbarkeit mit Between-Designs</div>
<p class="help-p"><strong style="color:var(--ink)">d<sub>av</sub> ist am ehesten mit Between-Designs vergleichbar.</strong> Da die Prä-Post-Korrelation nicht in den Nenner eingeht, ist d<sub>av</sub> — ceteris paribus — identisch mit Cohen's d aus einem unabhängigen Gruppenvergleich. Das ermöglicht eine direkte Gegenüberstellung über Designs hinweg: ein Within-d<sub>av</sub> von 0.5 bedeutet dasselbe wie ein Between-d<sub>s</sub> von 0.5. d<sub>z</sub> und d<sub>rm</sub> hingegen hängen von r ab und sind designspezifisch — deshalb verwendet dieses Tutorial d<sub>av</sub> als Effektgröße im Plot und in der Umrechnungstabelle.</p>
<div class="help-h3">Korrekturen für kleine Stichproben</div>
<p class="help-p">Cohens d ist ein nach oben verzerrter Schätzer der wahren Populations-Effektgröße δ — die Verzerrung hängt von den Freiheitsgraden ab, nicht vom wahren Effekt. Drei gebräuchliche Korrekturfaktoren überführen d in ein "Hedges' g":</p>
<p class="help-p"><code>j (Hedges 1981)</code> — j = 1 − 3/(4df−1); am gebräuchlichsten.<br>
<code>nag (Nakagawa & Cuthill 2007)</code> — eigene df-Zählung, empfohlen speziell für Messwiederholungen.<br>
<code>Bon (Bonett 2015)</code> — Bon = √((n−2)/(n−1)); basiert auf Varianz-Unbiasedness statt auf dem Erwartungswert von d, tendenziell konservativer.</p>
<p class="help-p">Bei n ≥ 40 unterscheiden sich die drei kaum; bei sehr kleinem n (z. B. < 15) können sie spürbar auseinanderfallen — probiere es mit dem n-Regler aus.</p>
<div class="help-h3">Cohen's U₃ und CLES</div>
<p class="help-p">Beide übersetzen d in eine Wahrscheinlichkeit und sind oft leichter zu kommunizieren als d selbst.</p>
<p class="help-p"><code>U₃ = Φ(d)</code> — der Anteil der Vergleichsgruppe (M₁), den der Mittelwert der anderen Gruppe (M₂) übertrifft (bei d = 0.5 also 69.1%).<br>
<code>CLES = Φ(d/√2)</code> — die Wahrscheinlichkeit, dass eine zufällig gezogene Person aus Gruppe 2 einen höheren Wert hat als eine zufällig gezogene Person aus Gruppe 1.</p>
<div class="help-h3">Weitere Umrechnungen</div>
<p class="help-p"><code>r = d/√(d²+4)</code> — punktbiseriale Korrelation zwischen Gruppenzugehörigkeit und Messwert.<br>
<code>r²</code> bzw. <code>η²</code> — Anteil der durch die Gruppierung aufgeklärten Varianz.<br>
<code>OR = exp(d·π/√3)</code> — Odds Ratio unter Normalverteilungsannahme, verbreitet in Medizin und Epidemiologie.</p>
<p class="help-p"><strong style="color:var(--ink)">Vorzeichen:</strong> r, OR, U₃ und CLES folgen alle demselben Vorzeichen wie d. Ist d negativ (M₂ < M₁, hier: eine Abnahme), fallen U₃ und CLES unter 50 %, OR unter 1, und r wird negativ — das ist kein Fehler, sondern zeigt konsistent dieselbe Richtung wie d an. Nur r² und η² sind vorzeichenunabhängig, weil sie aufgeklärte Varianz (quadrierte Größen) ausdrücken. Ob man Effektgrößen mit Vorzeichen berichtet oder den Betrag nimmt, ist selbst eine Konvention: das Vorzeichen sollte stehen bleiben, wenn die Richtung inhaltlich informativ ist (z. B. Zu- vs. Abnahme) — nur beim reinen Abgleich mit den klein/mittel/groß-Schwellen (die per Definition Beträge sind) wird auf den Betrag geschaut.</p>
<div class="help-h3">Für die eigene Studie</div>
<p class="help-p">Dieses Tutorial arbeitet mit einem festen (aber frei einstellbaren) Beispiel und zeigt keine Konfidenzintervalle. Für exakte Berechnungen mit eigenen Daten — CSV-Upload, Konfidenzintervalle nach Bonett, Rosenthal und exakter nichtzentraler t-Verteilung — siehe den <a href="Effektgroessen_Rechner.html">Effektgrößen-Rechner</a>.</p>
</div>
</div>
<div id="app">
<div id="sidebar">
<div class="scard">
<div class="scard-title">Design</div>
<div class="mode-row">
<button class="mode-btn active" id="mode-between" onclick="setMode('between')">Between<br><span style="font-size:.65rem;opacity:.7">Unabh. Gruppen</span></button>
<button class="mode-btn" id="mode-within" onclick="setMode('within')">Within<br><span style="font-size:.65rem;opacity:.7">Messwiederholung</span></button>
</div>
<div class="sb-note" id="mode-note">Zwei unabhängige Gruppen — der einfachere Fall: ein Nenner, eine Standardisierung.</div>
</div>
<div class="scard">
<div class="scard-title">Populationsparameter</div>
<div class="slider-row">
<div class="slider-lbl"><span class="slider-name" id="lbl-m1">M₁</span><span class="slider-val" id="v-m1">45.8</span></div>
<input type="range" id="sl-m1" min="30" max="65" step="0.1" value="45.8" oninput="onSlider()">
</div>
<div class="slider-row">
<div class="slider-lbl"><span class="slider-name" id="lbl-m2">M₂</span><span class="slider-val" id="v-m2">52.4</span></div>
<input type="range" id="sl-m2" min="30" max="65" step="0.1" value="52.4" oninput="onSlider()">
</div>
<div class="slider-row">
<div class="slider-lbl"><span class="slider-name" id="lbl-sd1">SD₁</span><span class="slider-val" id="v-sd1">8.4</span></div>
<input type="range" id="sl-sd1" min="2" max="15" step="0.1" value="8.4" oninput="onSlider()">
</div>
<div class="slider-row">
<div class="slider-lbl"><span class="slider-name" id="lbl-sd2">SD₂</span><span class="slider-val" id="v-sd2">9.6</span></div>
<input type="range" id="sl-sd2" min="2" max="15" step="0.1" value="9.6" oninput="onSlider()">
</div>
<div class="slider-row">
<div class="slider-lbl"><span class="slider-name" id="lbl-n">n</span><span class="slider-val" id="v-n">40</span></div>
<input type="range" id="sl-n" min="10" max="150" step="1" value="40" oninput="onSlider()">
</div>
<div class="slider-row" id="row-r" style="display:none">
<div class="slider-lbl"><span class="slider-name">r (Prä-Post)</span><span class="slider-val" id="v-r">.65</span></div>
<input type="range" id="sl-r" min="-90" max="90" step="1" value="65" oninput="onSlider()">
</div>
</div>
</div><!-- /sidebar -->
<div id="main">
<div class="p-intro">
<strong>Was ist eine Effektgröße?</strong> Ein p-Wert sagt nur, ob ein Unterschied von Null verschieden ist — nichts über seine praktische Bedeutsamkeit. Eine Effektgröße drückt aus, <em>wie groß</em> ein Unterschied ist, unabhängig von der verwendeten Skala und der Stichprobengröße. Die gebräuchlichste Effektgröße für Mittelwertsvergleiche ist <strong>Cohen's d</strong>: die Differenz zweier Mittelwerte, standardisiert an einer Streuung. d = 0.5 heißt: die beiden Verteilungen liegen im Mittel eine halbe Standardabweichung auseinander — egal ob es um Testpunkte oder Körpergröße geht. Das macht Effekte über Studien und Maße hinweg vergleichbar.
</div>
<div class="story-box" id="example-box"></div>
<div class="sec-h">Visualisierung: Wie stark unterscheiden sich die Gruppen?</div>
<div class="canvas-wrap">
<canvas id="overlap-canvas" height="390"></canvas>
<div class="canvas-axis-note" id="axis-note">x-Achse: Wohlbefinden-Score (fiktive Skala, wie im Beispiel) · Kurven = angenommene Populationsverteilungen beider Gruppen</div>
</div>
<!-- Point estimates -->
<div id="between-est">
<div class="results-section">
<div class="rs-head">Punktschätzer — Cohen's d (n−1 gepoolte SD)</div>
<div id="tbl-between"></div>
</div>
</div>
<div id="within-est" style="display:none">
<div class="results-section">
<div class="rs-head" style="color:var(--a2)">d<sub>z</sub> — Differenzen-SD als Nenner</div>
<div id="tbl-dz"></div>
</div>
<div class="results-section">
<div class="rs-head" style="color:var(--a6)">d<sub>rm</sub> — korrigiert für Messwiederholung (Becker 1988)</div>
<div id="tbl-drm"></div>
</div>
<div class="results-section">
<div class="rs-head" style="color:var(--a4)">d<sub>av</sub> — mittlere SD als Nenner (Lakens 2013), am ehesten mit Between vergleichbar</div>
<div id="tbl-dav"></div>
</div>
</div>
<div class="sec-h">Was bedeuten diese Zahlen?</div>
<div class="step-block">
<div class="step-h"><span class="circ">①</span> Unkorrigiert vs. korrigiert</div>
<div class="step-body">Die Spalte "unkorr." ist das rohe Cohen's d — ein leicht nach oben verzerrter Schätzer, besonders bei kleinem n. Die drei Korrekturspalten (g·j, g·nag, g·Bon) ziehen den Wert etwas näher an Null. Bei n = 40 ist der Unterschied klein; bei n < 15 kann er relevant werden — probiere es mit dem n-Regler aus.</div>
</div>
<div class="step-block" id="step-within-only" style="display:none">
<div class="step-h"><span class="circ">②</span> Drei Standardisierungen, eine Entscheidung</div>
<div class="step-body">Bei Messwiederholung liefern d<sub>z</sub>, d<sub>rm</sub> und d<sub>av</sub> unterschiedliche Werte — und keiner ist grundsätzlich "richtig". Erhöhe r im Regler: d<sub>z</sub> wird größer (die Differenzen-Streuung schrumpft), d<sub>av</sub> bleibt unverändert (r geht nicht in den Nenner ein). d<sub>rm</sub> liegt dazwischen und trifft bei r = .5 genau d<sub>z</sub>. Für Vergleiche mit Between-Designs (z. B. in einer Meta-Analyse) ist <strong>d<sub>av</sub></strong> die richtige Wahl, weil r nicht in den Nenner eingeht.</div>
</div>
<div class="step-block">
<div class="step-h"><span class="circ" id="step-conv-num">②</span> Effektgröße in andere Maße übersetzen</div>
<div class="step-body">Cohen's d lässt sich in weitere gebräuchliche Maße umrechnen — je nachdem, was im eigenen Feld üblich ist oder besser kommuniziert werden kann. <code>r</code> und <code>η²</code> sind aus der Varianzaufklärung bekannt, <code>OR</code> aus der Logistik-/Epidemiologie-Welt, <code>U₃</code> und <code>CLES</code> sind Wahrscheinlichkeits-basierte Maße ("wie oft übertrifft eine Person aus Gruppe 1 eine aus Gruppe 2?") und oft leichter zu vermitteln als d selbst.</div>
<table class="d-table" id="tbl-convert" style="margin-top:.5rem"></table>
</div>
<div class="step-block">
<div class="step-h"><span class="circ" id="step-caveat-num">③</span> Konventionen sind kein Naturgesetz</div>
<div class="step-body">Die Spalte "Konvention" in der Tabelle oben (0.2 / 0.5 / 0.8 für klein/mittel/groß) stammt von Cohen (1988) — eine grobe Faustregel, gemittelt über sehr unterschiedliche Verhaltens- und Sozialwissenschaften, gedacht für Situationen, in denen sonst gar keine Orientierung verfügbar war. Es ist <strong>keine feste Schwelle und keine empirisch hergeleitete Grenze</strong>. Derselbe Wert d = 0.3 kann in einem Kontext vernachlässigbar sein (z. B. bei einem folgenlosen Persönlichkeitsmerkmal) und in einem anderen enorm bedeutsam (z. B. bei einer Sterblichkeitsreduktion in einer Medikamentenstudie, oder einem kleinen Effekt, der über Millionen Nutzer:innen skaliert). Ob ein Effekt <em>praktisch bedeutsam</em> ist, lässt sich nicht aus der Statistik allein ablesen — das ist immer eine inhaltliche Entscheidung: abhängig vom Feld, von den Kosten und Risiken einer Intervention, vom Vergleich mit bereits bekannten Effekten in genau diesem Forschungsbereich, und von den praktischen Konsequenzen für die betroffenen Personen.</div>
</div>
<!-- Konzepte -->
<div class="learn-section">
<div class="sec-h">Konzepte & Grenzen</div>
<div class="lcard-grid">
<div class="lcard">
<div class="lcard-h">Warum ist Cohen's d verzerrt?</div>
<div class="lcard-body">Das rohe d überschätzt die wahre Populations-Effektgröße δ systematisch — stärker bei kleinem n. Die Verzerrung hängt von den Freiheitsgraden ab, nicht von der Größe des wahren Effekts. Deshalb gibt es mehrere Korrekturformeln statt einer einzigen: sie treffen leicht unterschiedliche Annahmen über die Stichprobenverteilung.</div>
</div>
<div class="lcard">
<div class="lcard-h">Hedges' j-Korrektur</div>
<div class="lcard-body">j = 1 − 3/(4df−1) (Hedges 1981). Die gebräuchlichste Korrektur, asymptotisch exakt und in den meisten Statistik-Programmen (z. B. R-Paket <code>effsize</code>) als Standard hinterlegt. Ergebnis wird als <strong>Hedges' g</strong> bezeichnet.</div>
</div>
<div class="lcard">
<div class="lcard-h">Nakagawa & Cuthill-Korrektur</div>
<div class="lcard-body">Eigene df-Zählung, die speziell für Messwiederholungsdesigns hergeleitet wurde (Nakagawa & Cuthill 2007). Berücksichtigt, dass bei Within-Designs effektiv mit den Paaren, nicht mit unabhängigen Beobachtungen gerechnet wird.</div>
</div>
<div class="lcard">
<div class="lcard-h">Bonett-Korrektur</div>
<div class="lcard-body">Bon = √((n−2)/(n−1)) (Bonett 2015). Beruht nicht auf dem Erwartungswert von d, sondern auf Varianz-Unbiasedness — einer anderen statistischen Zielgröße. Tendenziell etwas konservativer als j oder nag. Wird typischerweise bei <strong>Within-Designs</strong> herangezogen, wo sie neben j und nag als dritte Korrekturoption angeboten wird (siehe Tabellen oben).</div>
</div>
<div class="lcard">
<div class="lcard-h">Cohen's U₃</div>
<div class="lcard-body">U₃ = Φ(d): der Anteil der Referenzgruppe, den der Mittelwert der anderen Gruppe übertrifft. Bei d = 0 liegt U₃ bei 50%, bei d = 0.8 (großer Effekt) bei rund 78.8%. Leicht als "wie viel Prozent der Kontrollgruppe liegen unter dem Trainings-Mittelwert?" zu vermitteln.</div>
</div>
<div class="lcard">
<div class="lcard-h">CLES — Common Language Effect Size</div>
<div class="lcard-body">CLES = Φ(d/√2) (McGraw & Wong 1992): die Wahrscheinlichkeit, dass eine zufällig gezogene Person aus der einen Gruppe einen höheren Wert hat als eine zufällig gezogene Person aus der anderen. Anders als U₃ vergleicht CLES zwei einzelne Personen statt eine Person mit einer ganzen Verteilung.</div>
</div>
<div class="lcard">
<div class="lcard-h">r, r² und η²</div>
<div class="lcard-body">d lässt sich als punktbiseriale Korrelation r zwischen Gruppenzugehörigkeit und Messwert ausdrücken. r² (bzw. η² bei mehr als zwei Gruppen) ist der Anteil der durch die Gruppierung aufgeklärten Varianz — dasselbe Konzept wie bei linearer Regression, nur mit einer binären statt kontinuierlichen Prädiktorvariable.</div>
</div>
<div class="lcard">
<div class="lcard-h">Odds Ratio</div>
<div class="lcard-body">OR = exp(d·π/√3) approximiert die Umrechnung zwischen Cohen's d und dem Chancenverhältnis unter der Annahme, dass eine zugrundeliegende Normalverteilung logistisch dichotomisiert wurde. Verbreitet in Medizin und Epidemiologie, wo Ergebnisse oft ohnehin als Odds Ratios berichtet werden.</div>
</div>
<div class="lcard">
<div class="lcard-h">Grenzen standardisierter Effektgrößen</div>
<div class="lcard-body">d ist nur vergleichbar, wenn die Populationsstreuungen ähnlich sind. Bei hochselektiven Stichproben (<a href="Range_Restriction.html">Range Restriction</a>) unterschätzt d den wahren Effekt. Messfehler zieht d durch <a href="Messfehler_Attenuierung.html">Attenuierung</a> zusätzlich nach unten.</div>
</div>
<div class="lcard rechner">
<div class="lcard-h">Für die eigene Studie</div>
<div class="lcard-body">Der <a href="Effektgroessen_Rechner.html"><strong>Effektgrößen-Rechner</strong></a> berechnet exakte Werte aus eigenen Daten (CSV-Upload) — inklusive Konfidenzintervallen nach Bonett, Rosenthal und exakter nichtzentraler t-Verteilung.</div>
</div>
<div class="lcard">
<div class="lcard-h">Unstandardisiert ist auch eine Effektgröße</div>
<div class="lcard-body">Standardisierung macht d einheitenlos und über Studien vergleichbar — aber genau dabei geht die Originalskala verloren. Eine unstandardisierte Mittelwertsdifferenz (im Plot oben: "Rohwertdiff. = …") oder ein unstandardisierter Regressionskoeffizient b sind oft <strong>unmittelbarer interpretierbar</strong>, weil sie in der Metrik der abhängigen Variable selbst vorliegen — einer Metrik, die man im eigenen Feld in der Regel gut kennt (Punkte auf einer bekannten Testskala, Tage Krankenhausaufenthalt, Euro Umsatz …). Ein d von 0.4 sagt für sich genommen wenig; ein Unterschied von "6 Punkten auf dem Wohlbefindens-Score" lässt sich dagegen direkt gegen bekannte Referenzwerte einordnen. Am informativsten ist meist, <strong>beides zu berichten</strong>: die Rohwert-Differenz für die inhaltliche Einordnung, die standardisierte Version für die Vergleichbarkeit über Studien hinweg.</div>
</div>
</div>
</div>
</div><!-- /main -->
</div><!-- /app -->
<script>
// ─── State ───────────────────────────────────────────────────────────────────
let state = { mode: 'between' };
// ─── Theme ────────────────────────────────────────────────────────────────────
function toggleTheme(){
const d=document.documentElement;
const dark=d.getAttribute('data-theme')==='dark';
const next=dark?'light':'dark';
d.setAttribute('data-theme',next);
localStorage.setItem('ml-theme',next);
document.getElementById('theme-btn').textContent=dark?'🌙 Dark':'☀ Light';
recompute();
}
function toggleHelp(){document.getElementById('help-overlay').classList.toggle('open')}
document.addEventListener('keydown',e=>{if(e.key==='Escape')document.getElementById('help-overlay').classList.remove('open')});
// ─── Mode switching ────────────────────────────────────────────────────────────
function setMode(m){
state.mode=m;
const isW=m==='within';
document.getElementById('mode-between').classList.toggle('active',!isW);
document.getElementById('mode-within').classList.toggle('active',isW);
document.getElementById('mode-note').textContent=isW
? 'Dieselben Personen vor und nach dem Training — hier entsteht die Standardisierungsfrage: SD wovon?'
: 'Zwei unabhängige Gruppen — der einfachere Fall: ein Nenner, eine Standardisierung.';
document.getElementById('lbl-m1').textContent=isW?'M₁ (Prä)':'M₁ (Kontrolle)';
document.getElementById('lbl-m2').textContent=isW?'M₂ (Post)':'M₂ (Training)';
document.getElementById('lbl-sd1').textContent=isW?'SD₁ (Prä)':'SD₁ (Kontrolle)';
document.getElementById('lbl-sd2').textContent=isW?'SD₂ (Post)':'SD₂ (Training)';
document.getElementById('lbl-n').textContent=isW?'n (Paare)':'n (pro Gruppe)';
document.getElementById('row-r').style.display=isW?'':'none';
document.getElementById('between-est').style.display=isW?'none':'';
document.getElementById('within-est').style.display=isW?'':'none';
document.getElementById('step-within-only').style.display=isW?'':'none';
document.getElementById('step-conv-num').textContent=isW?'③':'②';
document.getElementById('step-caveat-num').textContent=isW?'④':'③';
document.getElementById('example-box').innerHTML = isW
? '<div class="story-lbl">📋 Beispiel — Achtsamkeitstraining (Within)</div>Eine Psychologin untersucht, ob ein 8-wöchiges Achtsamkeitstraining das Wohlbefinden steigert. Dieselben Teilnehmenden werden vor (Prä) und nach (Post) dem Training befragt. Verändere M<sub>prä</sub>, M<sub>post</sub>, die Streuungen, die Prä-Post-Korrelation r und n mit den Reglern.'
: '<div class="story-lbl">📋 Beispiel — Achtsamkeitstraining (Between)</div>Eine Psychologin untersucht, ob ein 8-wöchiges Achtsamkeitstraining das Wohlbefinden steigert. Trainingsgruppe vs. Warteliste-Kontrollgruppe, je n Personen. Verändere die Mittelwerte und Streuungen beider Gruppen sowie n mit den Reglern.';
document.getElementById('axis-note').textContent = isW
? 'x-Achse: Wohlbefinden-Score (fiktive Skala) · Kurven = angenommene Verteilungen vor (blau) und nach (orange) dem Training'
: 'x-Achse: Wohlbefinden-Score (fiktive Skala) · Kurven = angenommene Verteilungen der Kontroll- (blau) und Trainingsgruppe (orange)';
recompute();
}
// ─── Math ────────────────────────────────────────────────────────────────────
function stdNorm(z){
const p=0.2316419,b1=0.319381530,b2=-0.356563782,b3=1.781477937,b4=-1.821255978,b5=1.330274429;
const t2=1/(1+p*Math.abs(z));
const poly=t2*(b1+t2*(b2+t2*(b3+t2*(b4+t2*b5))));
const pdf=Math.exp(-0.5*z*z)/Math.sqrt(2*Math.PI);
const q=1-pdf*poly;
return z>=0?q:1-q;
}
function fmt(x,d=3){return isNaN(x)||!isFinite(x)?'—':x.toFixed(d)}
function computeBetween(m1,m2,sd1,sd2,n){
const df=2*n-2;
const s_pool=Math.sqrt(((n-1)*sd1*sd1+(n-1)*sd2*sd2)/df);
const ds=(m2-m1)/s_pool;
const j=1-3/(4*df-1);
const gs=ds*j;
const cles_mw=stdNorm(ds/Math.sqrt(2));
return {mode:'between',ds,gs,cles_mw};
}
function computeWithin(m1,m2,sd1,sd2,n,r){
const m_dif=m2-m1;
const s_dif=Math.sqrt(sd1*sd1+sd2*sd2-2*r*sd1*sd2);
const s_av=Math.sqrt((sd1*sd1+sd2*sd2)/2);
const dz=m_dif/s_dif;
const drm=dz*Math.sqrt(2*(1-r));
const dav=m_dif/s_av;
const j=1-3/(4*(n-1)-1);
const nag=1-3/(4*(2*n-2)-1);
const bon=Math.sqrt((n-2)/(n-1));
const cles_mw=stdNorm(dav/Math.sqrt(2));
return {mode:'within',dz,drm,dav,j,nag,bon,cles_mw};
}
// ─── Tables ──────────────────────────────────────────────────────────────────
function buildPointTable(container, d, j, nag, bon, dname){
container.innerHTML='';
const tbl=document.createElement('table');
tbl.className='d-table';
const thead=document.createElement('thead');
const hr=document.createElement('tr');
['', dname+' (unkorr.)', 'g · j', 'g · nag', 'g · Bon'].forEach((t,i)=>{
const th=document.createElement('th'); th.textContent=t;
if(i>0) th.className='num';
hr.appendChild(th);
});
thead.appendChild(hr); tbl.appendChild(thead);
const tbody=document.createElement('tbody');
const tr=document.createElement('tr');
['Punktschätzer', fmt(d), fmt(d*j), fmt(d*nag), fmt(d*bon)].forEach((v,i)=>{
const td=document.createElement('td'); td.textContent=v;
td.className=i===0?'lbl':'num'; tr.appendChild(td);
});
tbody.appendChild(tr); tbl.appendChild(tbody);
container.appendChild(tbl);
}
function buildBetweenTable(r){
const c=document.getElementById('tbl-between');
c.innerHTML='';
const tbl=document.createElement('table');
tbl.className='d-table';
const thead=document.createElement('thead');
const hr=document.createElement('tr');
['', "d_s (unkorr.)", 'g_s (Hedges j-korr.)'].forEach((t,i)=>{
const th=document.createElement('th'); th.textContent=t;
if(i>0) th.className='num';
hr.appendChild(th);
});
thead.appendChild(hr); tbl.appendChild(thead);
const tbody=document.createElement('tbody');
const tr=document.createElement('tr');
['Punktschätzer', fmt(r.ds), fmt(r.gs)].forEach((v,i)=>{
const td=document.createElement('td'); td.textContent=v;
td.className=i===0?'lbl':'num'; tr.appendChild(td);
});
tbody.appendChild(tr); tbl.appendChild(tbody);
c.appendChild(tbl);
}
function buildConversionTable(d_ref, cles_mw){
const tbl=document.getElementById('tbl-convert');
tbl.innerHTML='';
const thead=document.createElement('thead');
const hrow=document.createElement('tr');
['Maß','Wert','Konvention (klein/mittel/groß)'].forEach((h,i)=>{
const th=document.createElement('th'); th.textContent=h;
th.style.width=i===0?'38%':i===1?'20%':'42%';
if(i===1) th.className='num';
hrow.appendChild(th);
});
thead.appendChild(hrow); tbl.appendChild(thead);
const tbody=document.createElement('tbody');
const d=d_ref;
const r=d/Math.sqrt(d*d+4);
const r2=r*r;
const eta2=d*d/(d*d+4);
const OR=Math.exp(d*Math.PI/Math.sqrt(3));
const u3=stdNorm(d)*100;
[
['d (Cohen)', fmt(d_ref,3), '0.2 / 0.5 / 0.8'],
['r (Pearson)', fmt(r,3), '0.1 / 0.3 / 0.5'],
['r² (Varianzerkl.)', fmt(r2,3), '0.01 / 0.09 / 0.25'],
['η² (eta²)', fmt(eta2,3), '0.01 / 0.06 / 0.14'],
['OR (Odds Ratio)', fmt(OR,2), '1.49 / 3.45 / 9.00'],
["Cohen's U₃", fmt(u3,1)+'%', '57.9 / 69.1 / 78.8%'],
['CLES (McGraw & Wong)', fmt(cles_mw*100,1)+'%', '55.6 / 63.8 / 71.4%'],
].forEach(row=>{
const tr=document.createElement('tr');
row.forEach((v,i)=>{
const td=document.createElement('td'); td.textContent=v;
td.className=i===1?'num':'lbl';
tr.appendChild(td);
});
tbody.appendChild(tr);
});
tbl.appendChild(tbody);
}
// ─── Canvas ──────────────────────────────────────────────────────────────────
function getC(){
const dark=document.documentElement.getAttribute('data-theme')==='dark';
return{
ink: dark?'#ece6d8':'#18130e', ink2: dark?'#8a8070':'#5a4f42', ink3: dark?'#857c68':'#8a7f72',
paper: dark?'#111520':'#f8f3e8', panel: dark?'#171d28':'#e8e0ce', grid: dark?'#1e242e':'#ddd5c5',
a2: dark?'#4ab0d8':'#2a6e8a', a5: dark?'#e07830':'#b85c00',
};
}
function niceStep(rough){
const mag=Math.pow(10,Math.floor(Math.log10(rough)));
const norm=rough/mag;
let step; if(norm<1.5) step=1; else if(norm<3) step=2; else if(norm<7) step=5; else step=10;
return step*mag;
}
// Draws the two actual raw-score population distributions (mean m_i, SD sd_i)
// on a shared raw-score x-axis; d is only used for the annotated arrow label.
function drawOverlap(m1, sd1, m2, sd2, d, lbl1, lbl2, cles_mw){
const H=390;
const cv=document.getElementById('overlap-canvas');
const W=cv.offsetWidth||800; cv.width=W; cv.height=H;
const ctx=cv.getContext('2d');
const C=getC();
ctx.fillStyle=C.panel; ctx.fillRect(0,0,W,H);
const padL=60, padR=60, padT=54, padB=140;
const plotW=W-padL-padR, plotH=H-padT-padB;
const yBase=padT+plotH;
const maxSD=Math.max(sd1,sd2);
const xMin=Math.min(m1,m2)-3.3*maxSD, xMax=Math.max(m1,m2)+3.3*maxSD;
const xpx=x=>padL+(x-xMin)/(xMax-xMin)*plotW;
function dens(x,mu,sd){ const z=(x-mu)/sd; return Math.exp(-0.5*z*z)/(sd*Math.sqrt(2*Math.PI)); }
const peak1=dens(m1,m1,sd1), peak2=dens(m2,m2,sd2);
const yPeak=plotH*0.72;
const scaleY=yPeak/Math.max(peak1,peak2);
function drawDist(mu,sd,col){
const xL=mu-4.2*sd, xR=mu+4.2*sd;
ctx.beginPath(); ctx.moveTo(xpx(xL),yBase);
for(let i=0;i<=300;i++){ const x=xL+i*(xR-xL)/300; ctx.lineTo(xpx(x), yBase-dens(x,mu,sd)*scaleY); }
ctx.lineTo(xpx(xR),yBase); ctx.closePath();
ctx.globalAlpha=0.22; ctx.fillStyle=col; ctx.fill(); ctx.globalAlpha=1;
ctx.strokeStyle=col; ctx.lineWidth=2.2; ctx.beginPath();
for(let i=0;i<=300;i++){ const x=xL+i*(xR-xL)/300; const py=yBase-dens(x,mu,sd)*scaleY; i===0?ctx.moveTo(xpx(x),py):ctx.lineTo(xpx(x),py); }
ctx.stroke();
}
// Overlap shading (min of the two densities, each with its own SD)
ctx.beginPath();
for(let i=0;i<=600;i++){
const x=xMin+i*(xMax-xMin)/600;
const py=yBase-Math.min(dens(x,m1,sd1),dens(x,m2,sd2))*scaleY;
i===0?ctx.moveTo(xpx(x),py):ctx.lineTo(xpx(x),py);
}
for(let i=600;i>=0;i--){ const x=xMin+i*(xMax-xMin)/600; ctx.lineTo(xpx(x),yBase); }
ctx.closePath();
ctx.globalAlpha=0.18; ctx.fillStyle=C.ink3; ctx.fill(); ctx.globalAlpha=1;
drawDist(m1,sd1,C.a2);
drawDist(m2,sd2,C.a5);
// Baseline
ctx.strokeStyle=C.grid; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(padL,yBase); ctx.lineTo(W-padR,yBase); ctx.stroke();
// X-axis ticks at "nice" raw-score intervals
const step=niceStep((xMax-xMin)/6);
const t0=Math.ceil(xMin/step)*step;
ctx.fillStyle=C.ink3; ctx.font='12px DM Mono,monospace'; ctx.textAlign='center';
for(let v=t0; v<=xMax; v+=step){
const px=xpx(v);
ctx.strokeStyle=C.grid; ctx.lineWidth=1;
ctx.beginPath(); ctx.moveTo(px,yBase); ctx.lineTo(px,yBase+5); ctx.stroke();
ctx.fillText(v.toFixed(step<1?1:0),px,yBase+18);
}
// Mean lines + group labels (positioned above each curve's own peak)
[[m1,sd1,C.a2,lbl1,peak1],[m2,sd2,C.a5,lbl2,peak2]].forEach(([mu,sd,col,lbl,peak])=>{
const px=xpx(mu);
ctx.strokeStyle=col; ctx.lineWidth=1.5; ctx.setLineDash([5,3]);
ctx.beginPath(); ctx.moveTo(px,padT+8); ctx.lineTo(px,yBase); ctx.stroke();
ctx.setLineDash([]);
ctx.fillStyle=col; ctx.font='bold 13px DM Mono,monospace'; ctx.textAlign='center';
const peakY=yBase-peak*scaleY-8;
ctx.fillText(lbl, px, Math.max(padT-6,peakY));
});
// d arrow between the two raw means
const px1=xpx(m1), px2=xpx(m2);
const arrY=yBase+40;
ctx.strokeStyle=C.ink; ctx.lineWidth=1.8; ctx.setLineDash([]);
ctx.beginPath(); ctx.moveTo(px1,arrY); ctx.lineTo(px2,arrY); ctx.stroke();
const ah=6;
[[px1,px2>px1?1:-1],[px2,px2>px1?-1:1]].forEach(([px,dir])=>{
ctx.beginPath(); ctx.moveTo(px,arrY); ctx.lineTo(px+dir*ah,arrY-ah); ctx.moveTo(px,arrY); ctx.lineTo(px+dir*ah,arrY+ah); ctx.stroke();
});
ctx.fillStyle=C.ink; ctx.font='bold 13px DM Mono,monospace'; ctx.textAlign='center';
ctx.fillText('Rohwertdiff. = '+fmt(m2-m1,1)+' → d = '+fmt(d,3), (px1+px2)/2, arrY+18);
// Stats box (U3 / CLES) — short labels; full definitions live in the Hilfe/step text below
const u3=stdNorm(d)*100;
const bw=Math.min(230,plotW), bx=padL+(plotW-bw)/2, by=arrY+34, bh=48;
ctx.fillStyle=C.paper; ctx.strokeStyle=C.grid; ctx.lineWidth=1;
ctx.fillRect(bx,by,bw,bh); ctx.strokeRect(bx,by,bw,bh);
ctx.fillStyle=C.ink2; ctx.font='11px DM Mono,monospace'; ctx.textAlign='left';
ctx.fillText("Cohen's U₃ = "+u3.toFixed(1)+'%', bx+10, by+18);
ctx.fillText('CLES = '+(cles_mw*100).toFixed(1)+'%', bx+10, by+34);
}
// ─── Input handling ────────────────────────────────────────────────────────────
function onSlider(){
document.getElementById('v-m1').textContent=fmt(parseFloat(document.getElementById('sl-m1').value),1);
document.getElementById('v-m2').textContent=fmt(parseFloat(document.getElementById('sl-m2').value),1);
document.getElementById('v-n').textContent=document.getElementById('sl-n').value;
document.getElementById('v-sd1').textContent=fmt(parseFloat(document.getElementById('sl-sd1').value),1);
document.getElementById('v-sd2').textContent=fmt(parseFloat(document.getElementById('sl-sd2').value),1);
document.getElementById('v-r').textContent=fmt(parseFloat(document.getElementById('sl-r').value)/100,2).replace('0.','.');
recompute();
}
function recompute(){
const m1=parseFloat(document.getElementById('sl-m1').value);
const m2=parseFloat(document.getElementById('sl-m2').value);
const n=parseInt(document.getElementById('sl-n').value);
const sd1=parseFloat(document.getElementById('sl-sd1').value);
const sd2=parseFloat(document.getElementById('sl-sd2').value);
const isW=state.mode==='within';
const lbl1=isW?'Prä':'Kontrolle';
const lbl2=isW?'Post':'Training';
if(isW){
const r=parseFloat(document.getElementById('sl-r').value)/100;
const res=computeWithin(m1,m2,sd1,sd2,n,r);
buildPointTable(document.getElementById('tbl-dz'), res.dz, res.j, res.nag, res.bon, 'd_z');
buildPointTable(document.getElementById('tbl-drm'), res.drm, res.j, res.nag, res.bon, 'd_rm');
buildPointTable(document.getElementById('tbl-dav'), res.dav, res.j, res.nag, res.bon, 'd_av');
buildConversionTable(res.dav, res.cles_mw);
drawOverlap(m1,sd1,m2,sd2, res.dav, lbl1, lbl2, res.cles_mw);
} else {
const res=computeBetween(m1,m2,sd1,sd2,n);
buildBetweenTable(res);
buildConversionTable(res.ds, res.cles_mw);
drawOverlap(m1,sd1,m2,sd2, res.ds, lbl1, lbl2, res.cles_mw);
}
}
// ─── Init ─────────────────────────────────────────────────────────────────────
window.addEventListener('resize', recompute);
if(document.documentElement.getAttribute('data-theme')==='light'){
const tb=document.getElementById('theme-btn');if(tb)tb.textContent='🌙 Dark';
}
setMode('between');
</script>
</body>
</html>