Erste Schritte mit R für Praktiker in den Biowissenschaften

Volker Kiefel

25. April 2021

Inhaltsverzeichnis

1  Hinweise zum Nachvollziehen der Beispiele
2  Ein-Stichproben-Analyse
    2.1  Perzentilen, Histogramm
    2.2  Mittelwert, Standardabweichung und Median
3  Einfache lineare Regression, Korrelationskoeffizient, Daten von einer Datei einlesen
4  Messung der Übereinstimmung der Beurteilung
    4.1  Cohens Kappa
    4.2  Spearmans und Kendalls Rangkorrelationskoefizient
5  Kontingenztafeln: Prüfung auf Unabhängigkeit, Trend
    5.1  Chiquadrat-Test
    5.2  G-Test (log likelihood ratio test)
    5.3  Prüfung von k×2-Feldertafeln auf Trend
    5.4  ,,Fisher's exakter Test''
    5.5  Odds ratio
6  Vertrauensgrenzen relativer Häufigkeiten bei binominalverteilter Grundgesamtheit
7  Vergleich mehrerer Gruppen
    7.1  Einfache Varianzanalyse
    7.2  Bartlett Test
8  ,,Goodness of fit''-Tests (Anpassungstests an bekannte Verteilungen)
    8.1  Kolmogorov-Smirnov Test für die Güte der Anpassung
    8.2  Shapiro-Wilk-Test
    8.3  Überprüfung von Genotyp-Häufigkeiten auf Vorliegen eines Hardy-Weinberg-Gleichgewichts
9  Vergleich von zwei unabhängigen Stichproben mit dem t-Test
10  Vergleich zweier abhängiger Stichproben im t-Test
11  Wilcoxon-Test für unabhängige Stichproben
12  Friedman-Test
13  Untersuchung auf Unterschiede der zentralen Tendenz bei Meßwerten in mehr als 2 Gruppen
    13.1  H-Test (Kruskal-Wallis)
    13.2  Multiple paarweise Vergleiche
14  Überlebenszeit-Analyse
    14.1  Beispieldaten aus der R-Implementation benutzen
    14.2  Kaplan Meier-Kurve, Daten aus eigener Datentabelle einlesen
15  Statistische Funktionen
    15.1  Chiquadrat-Verteilung
    15.2  F-Verteilung
    15.3  t-Verteilung (Student)
    15.4  Standardnormalverteilung
16  Bestimmung einer nowendigen Stichprobengröße
    16.1  Vergleich zweier Mittelwerte
    16.2  Vergleich zweier relativer Häufigkeiten
17  Metaanalyse
18  Erstellung von Grafiken
    18.1  Säulendiagramme
    18.2  Farben und andere Grafikparameter
    18.3  Boxplots
    18.4  Scatterplots
    18.5  Stripchart (eindimensionaler Scatterplot)
    18.6  Linien verbinden Werte von beliebig vielen Individuen, die zwei oder mehr Zeitpunkten oder Wiederholungen entsprechen
        18.6.1  Allgemeine Konstruktion mit plot()
        18.6.2  Konstruktion ähnlicher Diagramme mit interaction.plot()
19  Verschiedenes
    19.1  Berechnung der Determinante einer Matrix
    19.2  Datumsberechnungen
20  Anhang
    20.1  Hinweise für R unter Linux
        20.1.1  Installation
        20.1.2  R konfigurieren
        20.1.3  PDF-, PostScript- und EPS-Dateien von Abbildungen erstellen.
    20.2  Allgemeine Befehle
    20.3  Einstellen von Optionen des Systems
    20.4  Textdarstellung von R-Objekten als Textdatei speichern und wieder einlesen
    20.5  Datendateien für R formatieren
    20.6  Quellcodes
        20.6.1  ToR.awk
        20.6.2  Perc.R
21  Versionen
Index

Vorwort

Das vorliegende Manuskript ist eine kleine willkürlich zusammengestellte Sammlung von ,,Kochrezepten'' für die Anwendung von R1 mit Verfahren, wie sie von Biowissenschaftlern und Medizinern ständig benötigt werden. Dieser Text wurde in der Absicht geschrieben, dem Benutzer die allerersten Schritte mit R anhand von ihm vertrauten Problemen zu erleichtern. Vor allem benötigt man häufig in der Eile ein Beispiel, anhand dessen man rasch die Eingabe der Daten und die Formulierung einer Auswertung ausführen kann. In diesem Sinne dient dieses Manuskript auch dem Autor als Gedächtnisstütze.
Es empfiehlt sich dringend, parallel zum Ausprobieren der Beispiele zu wichtigen Funktionen die R-Dokumentation zu lesen, um zu erkennen, wie die in diesem Text verwendeten Lösungen in der oft sehr knappen Beschreibung ,,aussehen''. So wird man dann lernen, alternative und möglicherweise bessere Lösungen zu finden.
Das Manuskript ersetzt nicht die ausgezeichnete Dokumentation zur Beschreibung von R und es ersetzt nicht Lehrbücher oder Originalarbeiten zu statischen Methoden. Vor oder gleichzeitig mit diesem Dokument sollte man sich mit elementaren Datenstrukturen und Funktionen vertraut machen, darunter Vektoren, Listen, Arrays, ,,data frames'', read.table(), c(), z. B. in dem Dokument ,,An introduction to R'' des R development core teams, das jeder Installation von R beigefügt ist [1]. Installation und Nutzung der Windows-Version von R dürften weitgehend selbsterklärend sein. Hinweise auf Besonderheiten von R unter Linux finden sich in Abschnitt 20.1.
Für die Richtigkeit der in diesem kleinen Manuskript gemachten Angaben wird keine Gewähr übernommen. In fast allen Fällen ist der beschriebene Weg zur Dateneingabe nicht der einzig mögliche. Bei zunehmender Vertrautheit mit R sollte die Originaldokumentation und Fachliteratur zu den zugrundeliegenden statistischen Verfahren zu Rate gezogen werden! Empfehlenswerte Texte für den Einstieg in elementare Verfahren anhand von R sind [1,2,3].


Kritzmow bei Rostock, im Februar 2021
V.K.

1  Hinweise zum Nachvollziehen der Beispiele

Nach Starten der R-Konsole können die Eingaben aus dem Manuskript eingetippt werden, sie können aber auch aus der HTML-Version des Dokuments herauskopiert werden und an der Eingabeaufforderung der R Konsole mit einem paste-Befehl eingefügt werden.
Kurze Eingaben sind im Folgenden durch die mit abgebildete Eingabeaufforderung:
am Zeilenbeginn gekennzeichnet. Bei langen Eingabezeilen wird durch das + in der Folgezeile die Fortsetzung einer langen Zeile signalisiert:
> 
+

Bei der Eingabe sollen diese Zeichen ,,>'' und ,,+'' bei einer zeilenweisen Eingabe nicht mit eingegeben oder hineinkopiert werden. Zeilen, die mit ,,>'' beginnen, kennzeichnen Eingaben am Prompt der R-Konsole. Nach der Eingabe, die mit [Enter] bestätigt wird, folgt dann die Ausgabe von R ohne Eingabeaufforderung am Zeilenbeginn, nach der letzten Ausgabe erscheint dann wieder die Eingabeaufforderung. In der PDF-Fassung dieses Manuskripts muss der Leser darauf achten, dass sich innerhalb der kurzen Listings auch ein Zeilenumbruch befinden kann, bei der HTML-Version des Manuskripts stört dies natürlich nicht.
Eine alternative Form der Eingabe von R-Befehlen besteht darin, R Code in eine Skriptdatei zu schreiben und diese dann mit dem Befehl
> source("rcodedatei.R")

einzulesen. Ein Beispiel hierzu findet sich in dem Abschnitt 2.1. Wenn die Zeilen der mit source() eingelesenen Skriptdatei auf der Konsole angezeigt werden sollen, ist der modifizierte Befehl
> source("rcodedatei.R",echo=TRUE)

Auch umfangreichere Datensätze schreibt man besser in eine Tabelle in einer Datei(zum Beispiel mit einem Texteditor) und liest sie von der R-Konsole mit der Funktion read.table() ein, ein Beispiel findet sich in Abschnitt 3.

2  Ein-Stichproben-Analyse

2.1  Perzentilen, Histogramm

Zur Berechnung der 97,5-Perzentile der 100 Haptoglobin-Werte im folgenen Code (Schreibmaschinenschrift) müssen diese zunächst eingegeben werden. Um die Werte für eine Berechnung zugänglich zu machen verwende man zunächst die ,,eingebaute'' Funktion quantile(). Um eine Berechnung vornehmen zu können, müssen die Daten mit der Funktion c() in einen Vektor mit dem Namen hapto überführt werden:
# Aus Reed et al., 1971
# Anfang Eingabe
hapto <- 
c(14, 21, 21, 30, 32, 35, 36, 36, 40, 44, 47, 48, 48, 48, 50, 51, 52, 54, 58,
59, 59, 62, 65, 66, 67, 67, 69, 71, 72, 76, 76, 77, 77, 77, 77, 78, 79, 79,
80, 81, 82, 84, 85, 86, 87, 87, 88, 88, 89, 90, 90, 93, 94, 94, 95, 96, 96,
97, 98, 98, 100, 100, 101, 101, 101, 103, 105, 106, 108, 108, 108, 109, 113,
114, 114, 114, 116, 116, 119, 126, 128, 129, 135, 136, 141, 142, 147, 147,
150, 161, 162, 170, 174, 174, 176, 179, 181, 191, 199, 225)
# Ende Eingabe

Die eingebaute Funktion quantile() von R ergibt:
> quantile(hapto,  0.975)
 97.5% 
186.25 
> 

also 186,25. Wenn mehr als ein Percentil (Quantil) abgefragt werden soll, also zusätzlich das 2,5-Perzentil und der Median (50-Perzentil), geschiht das mit der Eingabe:
> quantile(hapto,  c(0.025,0.5,0.975))
   2.5%     50%   97.5% 
 25.275  90.000 186.250 
> 

Ein Histogramm kann mit dem Kommando hist() gezeichnet werden:
hist(hapto)

Mit eigenen Achsenbeschriftungen, Achsengrenzen versehen:
> hist(hapto, xlim=c(0,250), ylim=c(0,25),
+ main="Distribution of Haptoglobin Concentration",
+ xlab="Haptoglobin Concentration", ylab="Frequency")
>

Daten können auch mit selbst geschriebenen Funktionen werden. So könnte man Perzentilen mit einer nichtparametrischen Methode (Reed, [4]) schätzen, der Quellcode der Funktion perc() in Abschnitt 20.6.1 kann in eine Skriptdatei (z. B. perc.R) im aktuellen Verzeichnis kopiert werden und dann mit
> source("perc.R")

eingelesen werden. Sofern auch der Vektor mit den hapto-Daten noch zur Verfügng steht, kann die 97,5-Perzentile mit
> perc(hapto,97.5)
[1] 194.8
>

berechnet werden (die Perzentile wird für diese Funktion als Prozentwert eingegeben). Das Resultalt unterscheidet sich etwas von dem bei der eingebauten Funktion quantile(), da hier ein anderes Verfahren verwendet wird. Das Verfahren aus [4] steht aber auch bei Verwendung von quantile() zur Verfügung:
> quantile(hapto,  0.975, type=6)
97.5% 
194.8 
> 

die entsprechende Methode wird mit ,,type=6'' angegeben, Einzelheiten der Syntax von quantile() können im Hilfesystem von R nachgelesen werden, das mit ,,help(quantile)'' aufgerufen wird2.

2.2  Mittelwert, Standardabweichung und Median

Mittelwert, Median und Standardabweichung sollen zu den Werten in perc berechnet werden:
> source("hapto.R")
> mean(hapto)
[1] 95.25
> sd(hapto)
[1] 42.71786
> median(hapto)
[1] 90

Eine Zusammenstellung einiger einiger Maßzahlen zu den Werten in einem Vektor kann aufgerufen werden mit:
> summary(hapto)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  14.00   67.00   90.00   95.25  114.00  225.00 
> 

Mit summary() werden also in diesem Kontext Minimalwert, Maximalwert, 25. und 75. Perzentile, arithmetischer Mittelwert und Median ausgegeben.

3  Einfache lineare Regression, Korrelationskoeffizient, Daten von einer Datei einlesen

Es soll die Ausgleichsgerade zu folgenden x- und y- Werten berechnet werden (das Beispiel stammt aus [5,Seite 103]):
     XWERT  YWERT
1       13     12
2       17     17
3       10     11
4       17     13
5       20     16
6       11     14
7       15     15

Die Daten werden in dieser Form in eine Textdatei mit dem Namen 1.dat mit einem Texteditor geschrieben. Sie werden anschliessend an der R-Eingabeaufforderung so eingelesen und ausgewertet:
> tafel <- read.table("1.dat", header=TRUE)
> x <- tafel$XWERT
> y <- tafel$YWERT
> res <- lsfit(x, y)
> ls.print(res)
Residual Standard Error=1.6695
R-Square=0.5023
F-statistic (df=1, 5)=5.0463
p-value=0.0746

          Estimate Std.Err t-value Pr(>|t|)
Intercept   7.7288  2.8621  2.7004   0.0428
X           0.4262  0.1897  2.2464   0.0746


Die nach diesem Verfahren geschätzte Ausgleichsgerade ist damit: y = 7,7288+ 0,4262. Zu diesem Ergebnis kommt man auch mit der angemesseneren Funktion lm():
> lm(y ~ x)

Call:
lm(formula = y ~ x)

Coefficients:
(Intercept)            x  
     7.7288       0.4262  

Der Betrag des Korrelationskoeffizienten kann als Quadratwurzel aus R-square bestimmt werden oder direkt mit der Funktion cor.test():
> cor.test(x,y)

	Pearson's product-moment correlation

data:  x and y
t = 2.2464, df = 5, p-value = 0.07461
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.09505521  0.95310396
sample estimates:
      cor 
0.7087357 

4  Messung der Übereinstimmung der Beurteilung

4.1  Cohens Kappa

Daten aus [6,Seite 459]: Zwei Beurteiler ,,A'' und ,,B'' klassifizieren 100 Patienten nach den Merkmalen ,,V'', ,,N'' und ,,P''; die Resultate dieses Vergleichs:

          B                 
       +----+----+---+
       |  V |  N | P |
   +---+----+----+---+
 A | V | 53 |  5 | 2 |
   | N | 11 | 14 | 5 |
   | P |  1 |  6 | 3 |
   +---+----+----+---+


Zur Auswertung werden die Felder der Tafel werden zeilenweise in einen Vektor eingelesen, dieser wird dann mit der Funktion matrix() in eine Matrix umgewandelt.
> library(vcd)
> daten <- c(53,5,2,11,14,5,1,6,3)
> mdaten <- matrix(daten, nrow=3, byrow=T)
> mdaten
     [,1] [,2] [,3]
[1,]   53    5    2
[2,]   11   14    5
[3,]    1    6    3
> Kappa(mdaten)
               value        ASE       lwr       upr
Unweighted 0.4285714 0.08728716 0.2574917 0.5996511
Weighted   0.4923077 0.10057994 0.2951746 0.6894407
> 

Resultat in [6]: 0,429

4.2  Spearmans und Kendalls Rangkorrelationskoefizient

Beispiel aus [7,Seite 310]:
> a <- c(7,6,3,8,2,10,4,1,5,9)
> b <- c(8,4,5,9,1,7,3,2,6,10)
> cor.test(a,b, method="spearman")

	Spearman's rank correlation rho

data:  a and b
S = 24, p-value = 0.003505
alternative hypothesis: true rho is not equal to 0
sample estimates:
      rho 
0.8545455 

>

Mit
> cor.test(a,b, method="kendall")

	Kendall's rank correlation tau

data:  a and b
T = 38, p-value = 0.004687
alternative hypothesis: true tau is not equal to 0
sample estimates:
      tau 
0.6888889 

> 

läßt sich zu den gleichen Daten Kendalls τ bestimmen.

5  Kontingenztafeln: Prüfung auf Unabhängigkeit, Trend

5.1  Chiquadrat-Test

Einzugeben sei die Tafel:
  14   22   32
  18   16    8
   8    2    0

Die Werte in einen Vektor und anschließend in eine Matrix überführen:
> r <- c(14, 18, 8, 22, 16, 2, 32, 8, 0)
> rm <- matrix(r, nrow=3)
 
> rm
     [,1] [,2] [,3]
[1,]   14   22   32
[2,]   18   16    8
[3,]    8    2    0


Berechnung mit der Funktion chisq.test
> chisq.test(rm)

         Pearson's Chi-squared test 

data:  rm 
X-squared = 21.5765, df = 4, p-value = 0.0002433 

Warning message: 
Chi-squared approximation may be incorrect in: chisq.test(rm) 
> 

Einzugeben sei die Vierfeldertafel [7,S. 270]:
   14  85
    4  77

> r <- c(15,85,4,77)
> mr <- matrix(r,byrow=T,nrow=2)
> mr
     [,1] [,2]
[1,]   15   85
[2,]    4   77
> chisq.test(mr)

        Pearson's Chi-squared test with Yates' continuity correction

data:  mr 
X-squared = 3.8107, df = 1, p-value = 0.05093

> chisq.test(mr,correct=F)

        Pearson's Chi-squared test

data:  mr 
X-squared = 4.8221, df = 1, p-value = 0.02810

> 


Bei Vierfeldertafeln ist offenbar als Vorgabe Yates' Kontinuitätskorrektur eingestellt, was im zweiten Aufruf abgewählt wurde.

5.2  G-Test (log likelihood ratio test)

Der G-Test ist als Funktion GTest im Paket DescTools implementiert. Beispiel aus [8,Seite 202]: Blütenfarbe (X) und Blattbeschaffenheit (Y) von 48 selten vorkommenen Planzen:
            X
Y           weiss    rosa
glatt          12       4
rauh            9      23

Eingabe:
> library(DescTools)
> werte <- c(12, 9, 4, 23)
> mwerte <- matrix(werte, nrow=2)
> mwerte
     [,1] [,2]
[1,]   12    4
[2,]    9   23
> GTest(mwerte,correct="yates")

	Log likelihood ratio (G-test) test of independence with Yates'
	correction

data:  mwerte
G = 7.8536, X-squared df = 1, p-value = 0.005072
> 

Bewertung: die beiden Merkmale sind nicht voneinander unabhängig.

5.3  Prüfung von k×2-Feldertafeln auf Trend

Die folgende Tafel soll auf Trend untersucht werden [7,Seite 365]:
          geheilt
Therapie  nach
Erfolg    spez.    Anzahl 
Score     Therapie therapiert
  1         2        10
  2        16        34
  3        22        36

Eingabe [2]:
> geheilt <- c(2,16,22)
> summe <- c(10,34,36)
> prop.trend.test(geheilt,summe,score=c(1,2,3))

        Chi-squared Test for Trend in Proportions

data:  geheilt out of summe ,
 using scores: 1 2 3 
X-squared = 5.2197, df = 1, p-value = 0.02233

Die gleiche Tafel würde beim Vergleich ohne Berücksichtigungs des Trends keine signifikanten Unterschiede erkennen lassen:
> tafel <- c(14, 18, 8, 22, 16, 2)
> tmatrix <- matrix(tafel, byrow = T, nrow = 2)
> tmatrix
     [,1] [,2] [,3]
[1,]   14   18    8
[2,]   22   16    2

> chisq.test(tmatrix)

        Pearson's Chi-squared test

data:  tmatrix 
X-squared = 5.4954, df = 2, p-value = 0.06407

5.4  ,,Fisher's exakter Test''

Einzugeben sei die Tafel:
   10   4
    2   8

> tf <- c(10, 2, 4 ,8)
> mtf <- matrix(tf, nrow=2)
> fisher.test(mtf, alternative="greater")

         Fisher's Exact Test for Count Data 

data:  mtf 
p-value = 0.01804 
alternative hypothesis: true odds ratio is greater than 1 
95 percent confidence interval:
 1.435748      Inf 
sample estimates:
odds ratio 
  8.913675 

Hier wurde der p-Wert für eine einseitige Fragestellung ermittelt. Für die zweiseitige Fragestellung:
> fisher.test(mtf, alternative="two.sided")

        Fisher's Exact Test for Count Data

data:  mtf 
p-value = 0.03607
alternative hypothesis: true odds ratio is not equal to 1 
95 percent confidence interval:
   1.114920 123.433541 
sample estimates:
odds ratio 
  8.913675 

5.5  Odds ratio

Eine weitere Möglichkeit zur Berechnung von Konfidenzintervallen einer Odds Ratio besteht in der Verwendung der Funktion oddsratio im Paket epitools (Beispiel aus [9,Seite 490])
> library(epitools)
> tabelle <- matrix(c(24,96,48,592),nrow=2,byrow=T)
> tabelle
> oddsratio(tabelle,method="midp",conf.level=0.95)
$data
          Outcome
Predictor  Disease1 Disease2 Total
  Exposed1       24       96   120
  Exposed2       48      592   640
  Total          72      688   760

$measure
          odds ratio with 95% C.I.
Predictor  estimate    lower    upper
  Exposed1 1.000000       NA       NA
  Exposed2 3.085417 1.779715 5.236565

$p.value
          two-sided
Predictor    midp.exact fisher.exact   chi.square
  Exposed1           NA           NA           NA
  Exposed2 0.0001004225 0.0001119003 1.780411e-05

$correction
[1] FALSE

attr(,"method")
[1] "median-unbiased estimate & mid-p exact CI"
>

6  Vertrauensgrenzen relativer Häufigkeiten bei binominalverteilter Grundgesamtheit

Fragestellung: Man bestimme den 95%-Vertrauensbereich für 7 Treffer unter 20 Beobachtungen.
> binom.test(7,20, conf.level=0.95)

        Exact binomial test

data:  7 and 20 
number of successes = 7, number of trials = 20, p-value = 0.2632
alternative hypothesis: true probability of success is not equal to 0.5 
95 percent confidence interval:
 0.1539092 0.5921885 
sample estimates:
probability of success 
                  0.35 

> 

Eine Alternative zur Eingabe wäre:
> binom.test(c(7, 13), conf.level=0.95)

Gelegentlich können große Zahlen nicht berechnet werden, dann kann als Alternative prop.test verwendet werden.
> prop.test(7,20, conf.level=0.95)

        1-sample proportions test with continuity correction

data:  7 out of 20, null probability 0.5 
X-squared = 1.25, df = 1, p-value = 0.2636
alternative hypothesis: true p is not equal to 0.5 
95 percent confidence interval:
 0.1630867 0.5905104 
sample estimates:
   p 
0.35 

Als weitere Alternative steht die Funktion binom.exact() aus dem Paket epitools zur Verfügung.

7  Vergleich mehrerer Gruppen

7.1  Einfache Varianzanalyse

Folgende Daten sollen in einer einfachen Varianzanalyse untersucht werden. Die Kennungen für die Gruppe müssen Zeichenketten sein. Wenn nicht, muß der Vektor mit den Gruppenkennungen in einen factor umgewandelt werden:
> gr <- factor(tf$gruppe)

Die Eingabe im Einzelnen:
   wert  gruppe
1     6       a
2     7       a
3     6       a
4     5       a
5     5       b
6     6       b
7     4       b
8     5       b
9     7       c
10    8       c
11    5       c
12    8       c

tafel <- read.table("1.dat")
tafel.aov <- aov(tafel$wert~tafel$gruppe)
> summary(tafel.aov)
             Df  Sum Sq Mean Sq F value Pr(>F)  
tafel$gruppe  2  8.0000  4.0000     3.6  0.071 .
Residuals     9 10.0000  1.1111                 
---
Signif. codes:  0  `***'  0.001  `**'  0.01  `*'  0.05  `.'  0.1  ` '  1 

Zwei weitere Möglichkeiten, am Beispiel [7,Seite 388]:
    
Stichprobe 1   2   3

Werte      3   4   8
           7   2   4
               7   6
               3

Eingabe der Daten
> wert <- c(3,7,4,2,7,3,8,4,6)
> gruppe <- c(1,1,2,2,2,2,3,3,3)
> gruppe<-factor(gruppe)

Variante 1:
> anova(lm(wert ~ gruppe))
Analysis of Variance Table

Response: wert
          Df  Sum Sq Mean Sq F value Pr(>F)
gruppe     2  6.8889  3.4444  0.6889 0.5379
Residuals  6 30.0000  5.0000               

Variante 2:
> oneway.test(wert ~ gruppe,var.equal=T)

        One-way analysis of means

data:  wert and gruppe 
F = 0.6889, num df = 2, denom df = 6, p-value = 0.5379

> 

7.2  Bartlett Test

Der Bartlett-Test überprüft die Annahme, daß Streuungen in den Gruppen annähernd gleich sind. Die Daten aus [10,Seite 222, 228] werden in die Datei bartlett1.dat eingegeben:
Wert    Gruppe
13      1
9       1
15      1
5       1
25      1
15      1
3       1
9       1
6       1
12      1
42      2
24      2
41      2
19      2
27      2
8       3
24      3
9       3
18      3
9       3
24      3
12      3
4       3
9       4
12      4
7       4
18      4
2       4
18      4

Dann erfolgt die Auswertung mit
> tafel <- read.table("bartlett1.dat",header=TRUE)
> werte <- tafel$Wert
> gruppen <- factor(tafel$Gruppe)
> bartlett.test(werte, gruppen)

        Bartlett test for homogeneity of variances

data:  werte and gruppen 
Bartlett's K-squared = 1.6187, df = 3, p-value = 0.6552

> 

Die Nullhypothese zur Gleichheit der Varianzen wird demnach nicht abgelehnt.

8  ,,Goodness of fit''-Tests (Anpassungstests an bekannte Verteilungen)

8.1  Kolmogorov-Smirnov Test für die Güte der Anpassung

Daten aus [11,S. 186]:
         
>  da <- c(0.79, 0.68, 0.75, 0.73, 0.69, 0.77, 0.76, 0.74, 0.73, 0.68,
   + 0.72, 0.75, 0.71, 0.76, 0.69, 0.72, 0.70, 0.77, 0.71, 0.74)

> ks.test(da, "pnorm", mean=mean(da), sd=sqrt(var(da)))

         One-sample Kolmogorov-Smirnov test 

data:  da 
D = 0.0901, p-value = 0.997 
alternative hypothesis: two.sided 

Die Normalverteilungshypothese kann nicht verworfen werden.

8.2  Shapiro-Wilk-Test

Beispiel aus [12,Seite 398-399]: sind die Gewinne an Gewicht von sieben Ratten (70, 85, 94, 101, 107, 118, 132) normalverteilt?

> werte <- c(70, 85, 94, 101, 107, 118, 132)
> shapiro.test(werte)

        Shapiro-Wilk normality test

data:  werte 
W = 0.998, p-value = 1 


Es spricht nichts gegen die Annahme, daß die zugrundeliegende Verteilung normalverteilt ist.

8.3  Überprüfung von Genotyp-Häufigkeiten auf Vorliegen eines Hardy-Weinberg-Gleichgewichts

Beispiel aus [13]. Beobachtete Aufspaltungsziffern für Br(a/a), Br(a/b), Br(b/b):
   |---------+---------+---------|
   | Br(a/a) | Br(a/b) | Br(b/b) |
   |---------+---------+---------|
   |       1 |      22 |      86 |
   |---------+---------+---------|

Dateneingabe (das Br(a/b) Antigensystem erhielt später den Namen HPA-5):
> library(genetics)

  ...

> hpa5 <- c(rep("A/A",1),rep("A/B",22),rep("B/B",86))
> g1 <- genotype(hpa5)
> summary(g1)

Number persons typed: 109 (100%)

Allele Frequency: (2 alleles)
  Count Proportion
A    24       0.11
B   194       0.89


Genotype Frequency:
    Count Proportion
A/A     1       0.01
B/A    22       0.20
B/B    86       0.79

Heterozygosity (Hu)  = 0.1977574
Poly. Inf. Content   = 0.1767463

> HWE.chisq(g1,simulate.p.value=FALSE,correct=FALSE)

        Pearson's Chi-squared test

data:  tab 
X-squared = 0.0985, df = 1, p-value = 0.7536

Warning message: 
Chi-squared approximation may be incorrect in: chisq.test(tab, ...) 
> 


Das gleiche Ergebnis erhält man auch bei manualler Berechnung: Für ein dialleles System bestimmt man die Häufigkeit der Allele (im Br(a/b)-Beispiel ergibt sich 24/(2*109) für Br(a) und 194/(2*109) für Br(b)) und berechnet die zu erwartenden Aufspaltungshäufigkeiten, wenn p die Häufigkeit des Allels a und q die Häufigkeit des Allels b ist, gemäß p2, 2pq, q2, die entsprechenden Häufigkeiten sind 1,32110, 21,35780 und 86,32110. Dann bestimmt man für alle drei Genotypen den Ausdruck [((B−E)2)/E] (B: beobachtete Häufigkeit, E: erwartete Häufigkeit) und berechnet die Summe dieser drei Werte, die für die Bewertung der Nullhypothese in diesem Beispiel wie χ2 mit einem Freiheitsgrad verteilt ist [7,Seite 251]. Im Beispiel ergibt das χ2 = 0,09855. Damit gibt es keinen Anlaß für die Ablehnung der Nullhypothese.
Die Verwendung einer anderen Funktion aus dem genetics-Paket ergibt:
> HWE.exact(g1)

        Exact Test for Hardy-Weinberg Equilibrium

data:  g1 
N11 = 86, N12 = 22, N22 = 1, N1 = 194, N2 = 24, p-value = 1

9  Vergleich von zwei unabhängigen Stichproben mit dem t-Test

Die Syntax lautet:
> t.test(x,y)

Oft befinden sich die Daten beider zu vergleichenden Gruppen in einem Vektor und müssen aus diesem angand der Gruppenkennungen in einem zweiten Vektor ,,extrahiert'' werden. Beispiel aus P. Armitage und G. Berry: Statistical Methods in Medical Research, S 113.
   0        1.0      
   0        1.3      
   1        1.3      
   1        1.4      
   1        1.9      
   1        2.0      
   2        2.1      
   2        2.6      
   3        2.9

Dateneingabe: der Vektor werte enthält die Daten, der Vektor gr definiert die Zugehärigkeit zu Gruppen 1, 2:
> werte <- c(0,0,1,1,1,1,2,2,3,1,1.3,1.3,1.4,1.9,2,2.1,2.6,2.9)
> gr <- c(rep(1,9), rep(2,9))
> gr <- factor(gr)
> t.test(werte[gr==1], werte[gr==2])

         Welch Two Sample t-test 

data:  werte[gr == 1] and werte[gr == 2] 
t = -1.5753, df = 13.844, p-value = 0.1378 
alternative hypothesis: true difference in means is not equal to 0 
95 percent confidence interval:
 -1.4440276  0.2218053 
sample estimates:
mean of x mean of y 
 1.222222  1.833333 

> 

10  Vergleich zweier abhängiger Stichproben im t-Test

Beide Wertereihen werden in Vektoren eingetragen:
> a <- c(4, 3.5, 4.1, 5.5, 4.6, 6, 5.1, 4.3)
> b <- c(3, 3, 3.8, 2.1, 4.9, 5.3, 3.1, 2.7)
> t.test(a,b, paired = TRUE)

         Paired t-test 

data:  a and b 
t = 2.798, df = 7, p-value = 0.0266 
alternative hypothesis: true difference in means is not equal to 0 
95 percent confidence interval:
 0.1781177 2.1218823 
sample estimates:
mean of the differences 
                   1.15 

11  Wilcoxon-Test für unabhängige Stichproben

Beispiel aus [7,Seite 234]
Die Daten:
Stichprobe A:  7 14 22 36 40 48 49 52
Stichprobe B:  3  5  6 10 17 18 20 39

Bei der manuellen Eingabe wird die Gruppenzugehörigkeit wird durch die Faktorwerte von gruppe signalisiert:
> werte <- c(7,14,22,36,40,48,49,52,3,5,6,10,17,18,20,39)
> gruppe <- c(rep(1,8), rep(2,8))
> gruppe <-  factor(gruppe)
> wilcox.test(werte[gruppe==1], werte[gruppe==2], alternative="greater")

         Wilcoxon rank sum test 

data:  werte[gruppe == 1] and werte[gruppe == 2] 
W = 53, p-value = 0.01406 
alternative hypothesis: true mu is greater than 0 

> 


Alternativhypothese: Werte in Gruppe 1 sind größer.

12  Friedman-Test

groups in der Dokumentation sind ,,Behandlungen'', blocks sind Individuen, Stichprobengruppen oder Blöcke. Beide Eingabemöglichkeiten werden demonstriert. Beispiel aus Sachs:
      Gruppe  1     2     3     4
Block                                  
  1           27    23    26    21     
  2           27    23    25    21     
  3           25    21    26    20     

Die erste Variante ist günstig für die manuelle Eingabe
> tafel <- c(27, 27, 25, 23, 23, 21, 26, 25, 26, 21, 21, 20)
> mtafel <- matrix(tafel, nrow=3)
> friedman.test(mtafel)

         Friedman rank sum test 

data:  mtafel 
Friedman chi-squared = 8.2, df = 3, p-value = 0.04205 


Diese Form der eingabe ist geeignet für das Auslesen aus einer Datei:
> werte <- c(27, 23, 26, 21, 27, 23, 25, 21, 25, 21, 26, 20)
> gruppe <- c(rep(c(1,2,3,4),3))
> gruppe <- factor(grupppe)
> block <- c(rep(1, 4), rep(2, 4), rep(3, 4))
> block <- factor(block)
> friedman.test(werte, gruppe, block)

         Friedman rank sum test 

data:  werte, gruppe and block 
Friedman chi-squared = 8.2, df = 3, p-value = 0.04205 

13  Untersuchung auf Unterschiede der zentralen Tendenz bei Meßwerten in mehr als 2 Gruppen

13.1  H-Test (Kruskal-Wallis)

Wenn mehr Meßwerte in mehr als zwei Gruppen miteinender verglichen werden müssen und dabei Rangdaten verwendet werden sollen, kann man auf das grundsätzliche Vorhandensein von Unterschieden zwischen den Gruppen mit dem H-Test prüfen. Beispiel aus Sachs (1984):
    A       B        C        D                        
 12.1    18.3     12.7      7.3                     
 14.8    49.6     25.1      1.9                        
 15.3    10.1     47.0      5.8                        
 11.4    35.6     16.3     10.1                        
 10.8    26.2     30.4      9.4                        
          8.9                                          

> kwdaten <- c(12.1, 14.8, 15.3, 11.4, 10.8)
> kwdaten <- c(kwdaten, 18.3, 49.6, 10.1, 35.6, 26.2, 8.9)
> kwdaten <- c(kwdaten, 12.7, 25.1, 47.0, 16.3, 30.4)
> kwdaten <- c(kwdaten, 7.3, 1.9, 5.8, 10.1, 9.4)
> kwgruppe <- c(rep(1,5), rep(2,6), rep(3,5), rep(4,5))
> kruskal.test(kwdaten, kwgruppe)

         Kruskal-Wallis rank sum test 

data:  kwdaten and kwgruppe 
Kruskal-Wallis chi-squared = 11.5302, df = 3, p-value = 0.009179 

alternative Form der Eingabe
> gra <- c(12.1, 14.8, 15.3, 11.4, 10.8)
> grb <- c(18.3, 49.6, 10.1, 35.6, 26.2, 8.9)
> grc <- c(12.7, 25.1, 47.0, 16.3, 30.4)
> grd <- c(7.3, 1.9, 5.8, 10.1, 9.4)
> res <- kruskal.test(list(gra, grb, grc, grd))
> res

        Kruskal-Wallis rank sum test

data:  list(gra, grb, grc, grd) 
Kruskal-Wallis chi-squared = 11.5302, df = 3, p-value = 0.009179 

> 

13.2  Multiple paarweise Vergleiche

Zur Klärung der Frage, zwischen welchen Gruppen bedeutsame Unterschiede festzustellen sind, wenn zuvor die Nullhypothese mit dem H-Test abgelehnt wurde, prüft man anhand mittlerer Rangwertdifferenzen z.B. mit dem Verfahren nach Conover [14,Seite 290]. Eine Implementation, ConoverTest(), findet sich im Paket DescTools. Das folgende Beispiel stammt aus dem Buch von Conover [14,S. 290-292], die Dateneingabe:
gr1 <- c(83,91,94,89,89,96,91,92,90)
gr2 <- c(91,90,81,83,84,83,88,91,89,84)
gr3 <- c(101,100,91,93,96,95,94)
gr4 <- c(78,82,81,77,79,81,80,81)

daten <- list(gr1,gr2,gr3,gr4)
kruskal.test(daten)
library(DescTools)
ConoverTest(daten)

Die Resulate:
> kruskal.test(daten)

	Kruskal-Wallis rank sum test

data:  daten
Kruskal-Wallis chi-squared = 25.629, df = 3, p-value = 1.141e-05

...

> ConoverTest(daten)

 Conover's test of multiple comparisons : holm  

    mean.rank.diff    pval    
2-1      -6.533333 0.00794 ** 
3-1       7.738095 0.00794 ** 
4-1     -17.020833 3.2e-07 ***
3-2      14.271429 7.7e-06 ***
4-2     -10.487500 0.00029 ***
4-3     -24.758929 5.3e-10 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

>

Die Tabelle gibt die mittleren Rangdifferenzen und die p-Werte zu den Einzelvergleichen zwischen den Gruppen aus. Einzelheiten finden sich in der Dokumentation von DescTools und in [14]. Es gibt eine Reihe alternativer Methoden für solche post hoc Einzelvergleiche.

14  Überlebenszeit-Analyse

14.1  Beispieldaten aus der R-Implementation benutzen

Der Aufruf der Daten des Datensatzes leukemia aus dem survival-Paket ist in [15,Seite 238-9] beschrieben.

> library(survival)
> data(leukemia)

> leukemia
   time status             x
1     9      1    Maintained
2    13      1    Maintained
3    13      0    Maintained
4    18      1    Maintained
5    23      1    Maintained
6    28      0    Maintained
7    31      1    Maintained
8    34      1    Maintained
9    45      0    Maintained
10   48      1    Maintained
11  161      0    Maintained
12    5      1 Nonmaintained
13    5      1 Nonmaintained
14    8      1 Nonmaintained
15    8      1 Nonmaintained
16   12      1 Nonmaintained
17   16      0 Nonmaintained
18   23      1 Nonmaintained
19   27      1 Nonmaintained
20   30      1 Nonmaintained
21   33      1 Nonmaintained
22   43      1 Nonmaintained
23   45      1 Nonmaintained
> leuk.fit <- survfit(Surv(time, status)~x, leukemia)
> summary(leuk.fit)
Call: survfit(formula = Surv(time, status) ~ x, data = leukemia)

                x=Maintained 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    9     11       1    0.909  0.0867       0.7541        1.000
   13     10       1    0.818  0.1163       0.6192        1.000
   18      8       1    0.716  0.1397       0.4884        1.000
   23      7       1    0.614  0.1526       0.3769        0.999
   31      5       1    0.491  0.1642       0.2549        0.946
   34      4       1    0.368  0.1627       0.1549        0.875
   48      2       1    0.184  0.1535       0.0359        0.944

                x=Nonmaintained 
 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    5     12       2   0.8333  0.1076       0.6470        1.000
    8     10       2   0.6667  0.1361       0.4468        0.995
   12      8       1   0.5833  0.1423       0.3616        0.941
   23      6       1   0.4861  0.1481       0.2675        0.883
   27      5       1   0.3889  0.1470       0.1854        0.816
   30      4       1   0.2917  0.1387       0.1148        0.741
   33      3       1   0.1944  0.1219       0.0569        0.664
   43      2       1   0.0972  0.0919       0.0153        0.620
   45      1       1   0.0000      NA           NA           NA

> plot(leuk.fit)
> survdiff(Surv(time, status)~x, data=leukemia, rho=0)
Call:
survdiff(formula = Surv(time, status) ~ x, data = leukemia, rho = 0)

                 N Observed Expected (O-E)^2/E (O-E)^2/V
x=Maintained    11        7    10.69      1.27      3.40
x=Nonmaintained 12       11     7.31      1.86      3.40

 Chisq= 3.4  on 1 degrees of freedom, p= 0.0653 
> 


Mit library(Survival) wird das Survival-Paket geladen, data(leukemia) lädt den Datensatz, leukemia zeigt die Daten an. Mit Surv() wird ein ,,Überlebenszeit-Objekt'' erstellt, survfit() berechnet und plot() zeichnet eine Überlebenszeitkurve (n. Kaplan Meier). Mit survdiff() wird die Signifikanz der Unterschiede zwischen den Überlebenszeiten3 bestimmt. In der Datentabelle ist unter time die Überlebenszeit beschrieben, mit status wird der censoring status4 beschrieben, unter x findet sich der Faktor, der die Gruppen definiert (,,maintenance chemotherapy given?'').

14.2  Kaplan Meier-Kurve, Daten aus eigener Datentabelle einlesen

Nach Daten aus [16,S. 75] soll eine Überlebenszeitkurve erstellt werden. Die geordnete Liste der Beobachtungen (Zeit in Tagen) sei:
1*,3,4*,5,5,6*,7,7,7*,8*

wobei mit * die censored Überlebenszeiten (,,Ereignis noch nicht eingetreten'') seien. Die Daten werden in die Datei km.dat eingetragen:
  time  status  
1   1     0     
2   3     1     
3   4     0     
4   5     1     
5   5     1     
6   6     0     
7   7     1     
8   7     1     
9   7     0     
10  8     0     

Die Auswertung und das Plotten der Kurve erfolgt dann mit:
> library(survival)
> tafel <- read.table("km.dat", header=T)
> attach(tafel)
> fit <- survfit(Surv(time, status) ~ 1, data=tafel)
> plot(fit)

Anmerkungen:
(1) Die rechte Seite der ,,Modellformel'' in survfit() für das Plotten einer Gruppe muss ,,~ 1'' lauten [17,Seite 67].
(2) Wenn
> attach(tafel)

nicht aufgerufen würde, müßte die Lebenzeitanalyse mit
> fit <- survfit(Surv(tafel$time, tafel$status), data=tafel)

veranlaßt werden.

15  Statistische Funktionen

15.1  Chiquadrat-Verteilung

> 1-pchisq(3.84, df=1)
[1] 0.05004352
> 1-pchisq(30.58, df=15)
[1] 0.009993624

15.2  F-Verteilung

Berechnung des p-Werts:
> 1-pf(9.55, df1=2, df2=3)
[1] 0.05001422

Berechnung des F-Werts (gegeben p, df1, df2):
> qf(0.025,df1=16,df2=26,lower.tail=F)
[1] 2.359684

15.3  t-Verteilung (Student)

> 1-pt(12.706,df=1) # fuer einseitigen Test
[1] 0.0250004
> 2*(1-pt(12.706,df=1)) # fuer zweiseitigen Test
[1] 0.0500008
> 2*(1-pt(2.787,df=25)) # fuer zweiseitigen Test
[1] 0.01001021

15.4  Standardnormalverteilung

> (1-pnorm(1.64485)) # fuer einseitigen Test
[1] 0.05000037
> 2*(1-pnorm(1.64485)) # fuer zweiseitigen Test
[1] 0.1000007
> 2*(1-pnorm(3.2905, mean=0, sd=1)) # fuer zweiseitigen Test
[1] 0.001000095

16  Bestimmung einer nowendigen Stichprobengröße

16.1  Vergleich zweier Mittelwerte

Beispiel 6.3 aus [12]: Vergleich der Lungenfunktion von zwei Gruppen von Männern (mit dem forced expiratory volume), zuvor bekannt eine Standardabweichung von 0.5, vorgegeben Signifikanzniveau von 0.05 für den zweiseitigen Test und eine Power von 0.8, wie groß müssen die Stichproben sein für die Erkennung einer Differenz von 0.25:
> power.t.test(delta=0.25, sd=0.5, sig.level=0.05, power=0.8, 
+ alternative="two.sided" )


     Two-sample t test power calculation 

              n = 63.76576
          delta = 0.25
             sd = 0.5
      sig.level = 0.05
          power = 0.8
    alternative = two.sided

 NOTE: n is number in *each* group 

Damit wird eine Sichprobengröße von 64 pro Gruppe benötigt.

16.2  Vergleich zweier relativer Häufigkeiten

Beispiel 6.5 aus [12]: Vergleich zweier Behandlungen: die eine Behandlung führt zu einer Erfolgsrate von 25%. Wenn eine alternative Behandlungsmethode zu einer Erfolgsrate vom 35% führt, wieviel Individuen müssen die zu untersuchenden Gruppen bei einem Signifikanzniveau von 0.05 und einer Power von 90% umfassen?
> power.prop.test(p1=0.25, p2=0.35, sig.level=0.05, 
+ alternative="two.sided", power=0.9)

     Two-sample comparison of proportions power calculation 

              n = 439.2309
             p1 = 0.25
             p2 = 0.35
      sig.level = 0.05
          power = 0.9
    alternative = two.sided

 NOTE: n is number in *each* group 

also werden pro Gruppe 440 Individuen benötigt.

17  Metaanalyse

Im folgenden wird ein Beispiel aus [18] nachvollzogen. In einer Metaanalyse werden Gruppen von Patienten mit perioperativer autologer Blutspende daraufhin untersucht, wie wahrscheinlich die Gabe von Fremdblut bei einer Operation sein wird. Hierzu wird das relative Risiko bestimmt. Verglichen werden diese Wahrscheinlichkeiten mit Kontrollgruppen ohne präoperative autologe Blutspende5. Die Eingabe in die Datei blood-tr1.txt:
name       n.trt   n.ctrl  tr.trt  tr.ctrl
busch      239     236     66      133
elawad     45      15      3       14
hedstrom   38      40      7       29
heiss1993  58      62      20      37
heiss1997  29      27      11      13
hoynck     131     137     30      84
kajikawa   10      21      1       13
lorentz    16      15      2       10

Die Eingaben6:
> library(rmeta)
> d1 <- read.table("blood-tr1.txt",header=TRUE)
> d1
       name n.trt n.ctrl tr.trt tr.ctrl
1     busch   239    236     66     133
2    elawad    45     15      3      14
3  hedstrom    38     40      7      29
4 heiss1993    58     62     20      37
5 heiss1997    29     27     11      13
6    hoynck   131    137     30      84
7  kajikawa    10     21      1      13
8   lorentz    16     15      2      10
> b <- meta.DSL(n.trt, n.ctrl, tr.trt, tr.ctrl, data=d1,statistic="RR",names=name)
> summary(b)
Random effects ( DerSimonian-Laird ) meta-analysis
Call: meta.DSL(ntrt = n.trt, nctrl = n.ctrl, ptrt = tr.trt, pctrl = tr.ctrl, 
    names = name, data = d1, statistic = "RR")
------------------------------------
            RR (lower  95% upper)
busch     0.49    0.39       0.62
elawad    0.07    0.02       0.21
hedstrom  0.25    0.13       0.51
heiss1993 0.58    0.38       0.87
heiss1997 0.79    0.43       1.45
hoynck    0.37    0.27       0.53
kajikawa  0.16    0.02       1.07
lorentz   0.19    0.05       0.72
------------------------------------
SummaryRR= 0.38  95% CI ( 0.26,0.54 )
Test for heterogeneity: X^2( 7 ) = 22.39 ( p-value 0.0022 )
Estimated random effects variance: 0.14 
> plot(b)
> 


Resultat: in der Gruppe mit präoperativer autologer Spende ist die Wahrscheinlichkeit 0.38 für eine Fremdbluttransfusion verglichen mit der Kontrollgruppe, anders formuliert: die präoperative autologe Spende reduziert das Risiko einer Fremdbluttransfusion um 62%.

18  Erstellung von Grafiken

Im folgenden Abschnit sind absichtlich die erzeugten Grafiken nicht wiedergegeben, die entsprechenden Quellcodefragmente sollen interaktiv am Propmpt eigegeben werden und man sieht dann, was passiert. Gleichzeitig sollte man die Dokumentation öffnen z. B. für Barplot mit help(barplot). Allmählich wird man dann weitergehend probieren können.

18.1  Säulendiagramme

Es soll ein Säulendiagramm mit den folgenden Werten erstellt werden:
> werte <- c(0.03, 0.04, 0.69, 1.25, 0.08, 0.058, 1.1)

Es erscheinen senkrechte Säulen in Regenbogenfarben, Farbe wird kontrolliert durch einen Vektor, der col zugewiesen wird
> farben <- rep(gray(0.7), 7)
> barplot(werte, col=farben)

nun sind alle Säulen hellgrau. Das Diagramm soll waagrechte Balken aufweisen:
> barplot(werte, col=farben, horiz=T)

Die Säulen sollen schmaler werden.
> barplot(werte, col=farben, horiz=T, space=3)

Darstellung gruppierter Säulen:
> werte <- c(0.03, 0.04, 0.69, 0.09, 1.25, 0.08, 0.58, 0.3)
> wertematrix <- matrix(werte, nrow=2)
> wertematrix
     [,1] [,2] [,3] [,4]
[1,] 0.03 0.69 1.25 0.58
[2,] 0.04 0.09 0.08 0.30

> barplot(wertematrix, col=farben, horiz=F)

Das ergibt ,,gestapelte Säulen'', nebeneinander gruppiere Säulen:
> barplot(wertematrix, col=farben, horiz=F, beside=T)

als horizontales gruppiertes Diagramm:
> barplot(wertematrix, col=farben, horiz=T, beside=T)

18.2  Farben und andere Grafikparameter

Dokumentation zu Grafikparametern erhält man mit
> help(par)

Eine Liste von Farben für col wird mit
> colors()

gezeigt.

18.3  Boxplots

Annähernd normalverteite Zufallswerte für 2 Gruppen werden erzeugt mit:
> werte1 <- rnorm(20, mean=10, sd=2)
> werte2 <- rnorm(50, mean=16, sd=2.6)
> boxplot(werte1, werte2)

Farbe, Bereich der y-Achse adjustieren
> boxplot(werte1, werte2, col="wheat1", ylim=c(0,25))

Gruppenbezeichnungen einfügen:
> boxplot(werte1, werte2, col="wheat1", ylim=c(0,30), 
+ names=c("group A", "group B"))

Körper der Boxen verschieden färben:
boxplot(werte1, werte2, col=c("wheat1","tomato2"), 
+ ylim=c(0,30), names=c("group A", "group B"), horizontal=T)

Ein Boxplot mit logarithmisch unterteilter y-Achse wird mit dem Zusatz log="y" gezeichnet:
e <- 2.7182818
werte1 <- rnorm(50, mean=6, sd=0.9)
werte1 <- e**werte1 
werte2 <- rnorm(50, mean=7, sd=1.0)
werte2 <- e**werte2
boxplot(werte1, werte2, col="tomato1", log="y", names=c("GR 1", "GR 2"))

Oft wird es notwendig sein, die Boxen in einem Boxplot zu gruppieren. Dazu kann man die Option at nehmen. Im folgenden ein weiteres komplettes Beispiel:
werteA1 <- rnorm(20, mean=12, sd=3)
werteA2 <- rnorm(20, mean=14, sd=3.4)
werteB1 <- rnorm(18, mean=15, sd=3.2)
werteB2 <- rnorm(22, mean=18, sd=4)
werteC1 <- rnorm(24, mean=10, sd=2.2)
werteC2 <- rnorm(17, mean=9, sd=2)
 boxplot(
         werteA1,
         werteA2,
         werteB1,
         werteB2,
         werteC1,
         werteC2,
         ylim=c(0,25),
         at = c(1.2,1.8,3.2,3.8,5.2,5.8),
         boxwex=0.4,
         ylab="microgram Ig/ml",
         names=c("A1","A2", "B1", "B2",
                 "C1","C2"), las=2)

abline(v=2.5)
abline(v=4.5)


Um die Positionen der Säulen gleichmäßig zu verteilen, müßte man at = c(1,2,3,4,5,6) eintragen. Mit boxwex skaliert man die Breite der Boxen. Mit zuätzlichen Linien (abline(...)) kann die Gruppierung deutlicher gemacht werden.

18.4  Scatterplots

Im folgenden Beispiel wird ein Plot nach und nach um weitere Punkte, Legenden ergänzt.
a <- c(1,2,2.5)
b <- c(2.6,4,6)

plot(a,b, xlim=c(0,3), ylim=c(0,8),
  ylab="Y-Werte", xlab="X-Werte", pch=2, col="red")

c <- c(1.1,1.6,1.8,2)
d <- c(2.1,3,3.4,6)
points(c,d, pch=3, type="b", col="blue")

e <- c(1.3,1.7,1.9)
f <- c(2.1,2.7,3.4)

points(e,f, pch=4, type="b", col="magenta")
legend(2.5,1.2,plot=T,legend=c("Group a","Group c","Group e"),pch=c(2,3,4),
   col=c("red","blue","magenta"))

18.5  Stripchart (eindimensionaler Scatterplot)

Während ein Boxplot ein abstrahiertes Bild der Verteilungsform liefert, ist es manchmal auch erwünscht, Originalwerte verschiedener Gruppen direkt zu plotten. Dazu kann man einen Stripchart verwenden.
A <- c(1, 3.4, 4, 4.2, 6, 12, 17)
B <- c(4, 8, 12, 13, 14.6, 18.9, 21.4, 14)
stripchart(list(A, B))

Gruppennamen werden vergeben und mit anderen Werten für ylim werden die beiden Punktesäulen etwas in die Mitte geholt.
stripchart(list(A, B), group.names=c("group A", "group B"), ylim=c(0.5,2.5))

Um die Beschriftung der y-Achse horizontal zu setzen und wird die Anweisung par(las=1) eingefügt und um den linken Rand zu verbreitern, par(mar=c(5,6,5,2). Damit sieht der Quellcode für die Erstellung des Diagramms so aus:
A <- c(1, 3.4, 4, 4.2, 6, 12, 17)
B <- c(4, 8, 12, 13, 14.6, 18.9, 21.4, 14)
stripchart(list(A, B))
par(las=1, mar=c(5,6,5,2))
stripchart(list(A, B), group.names=c("group A", "group B"), ylim=c(0.5,2.5))

Weitere Einzelheiten sind in der Dokumentation unter ?stripchart zu erfragen.
Eine Alternative besteht in der Verwendung von stripplot aus dem lattice-Paket:
library(lattice)
A <- c(1, 3.4, 4, 4.2, 6, 12, 17)
B <- c(4, 8, 12, 13, 14.6, 18.9, 21.4, 14)
trellis.device(color=FALSE)
gruppen <-  factor(c(rep("A", length(A)), rep("B", length(B))))
stripplot(c(A,B)~gruppen, ylab="Wert", horizontal=FALSE)

18.6  Linien verbinden Werte von beliebig vielen Individuen, die zwei oder mehr Zeitpunkten oder Wiederholungen entsprechen

18.6.1  Allgemeine Konstruktion mit plot()

par(adj = 0.5,
    xaxt ="n")
plot(
    # erste Linie
    c(1,2), c(2.262,0.014),  
    
    type = "b",
    xlim = c(0.6,2.4),
    ylim = c(0,3),
    ylab = "O. D.",
    xlab = ""
    )

text(1,2.9, vfont=c("sans serif", "plain"), cex=1.4, labels="before absorption")
text(2,2.9, vfont=c("sans serif", "plain"), cex=1.4, labels="after absorption")

# 2. und weitere Linien
lines(type="b", c(1,2), c(0.710,0.214))
lines(type="b", c(1,2), c(0.333,0.041))
lines(type="b", c(1,2), c(1.575,0.042))
lines(type="b", c(1,2), c(2.555,0.063))
lines(type="b", c(1,2), c(2.319,0.283))
lines(type="b", c(1,2), c(0.745,0.063))
lines(type="b", c(1,2), c(0.401,0.023))
lines(type="b", c(1,2), c(0.309,0.052))
lines(type="b", c(1,2), c(0.414,0.040))
lines(type="b", c(1,2), c(0.604,0.042))
lines(type="b", c(1,2), c(0.564,0.021))
lines(type="b", c(1,2), c(0.571,0.043))


lines(type="l", c(0.4,2.6),c(0.2,0.2))

Diese Art Darstellung setzt voraus, daß mit par(xaxt="n") die Beschriftung der x-Axhse ausgeschltet wird. Dann wird die erste Linie im Plot-Kommando gezeichnet, und dann folgen die weiteren Linien mit lines()-Befehlen.

18.6.2  Konstruktion ähnlicher Diagramme mit interaction.plot()

Im einfachsten Fall ist die Syntax des Befehls: interaction.plot(x.factor, trace.factor, response). Als Beispiel sei angenommen, daß Werte (values, im Diagramm mit ,,Intensity'' beschriftet) von vier Individuen (subject) zu drei verschiedenen Zeitpunkten (time: t0, t30, t90) untersucht wurden:
values = c(10,12,13,8,3,6,15,16,11,1,2,0.3)
time = rep(c("t0","t30","t90"),4)
subject= c(rep("no 1", 3),rep("no 2", 3),rep("no 3", 3),rep("no 4", 3))
interaction.plot(time,subject,values, ylab="Intensity")

Ein ähnliches Beispiel ist in [2,Seite 124] besprochen. Dieser Diagrammtyp ist meist geeignet zur Darstellung von Daten, die mit der Friedman-Rangvarianzanalyse untersucht werden.

19  Verschiedenes

19.1  Berechnung der Determinante einer Matrix

Im Beispiel werde für die Berechnung der Determinante:

D =



0
−3
−8
1
4
3
0
−15
−3




die Funktion det aus dem Paket base.
> da <- c(0,-3,-8,1,4,3,0,-15,-3)
> matda <- matrix(da, nrow=3, byrow=T)
> det(matda)
[1] 111

19.2  Datumsberechnungen

Berechung des Abstands zwischen zwei Daten in Tagen. Beispiel: berechnet werden soll der Abstand in Tagen zwischen 13.12.2000 und 20.4.2001:
> library(date)
> mdy.date(4,20,2001)-mdy.date(12,13,2000)
[1] 128
> 

Die Differenz beträgt also 128 Tage. Bestimmung des Datums n Tage vor oder nach einem gegebenen Daten: gesucht sei das Datum eines Tages 100 Tage nach dem 16.10.2007:
> mdy.date(10,16,2007)+100
[1] 24Jan2008
> 

Offenbar werden Daten intern als Ganzzahlen mit dem 1.1.1960 als Wert ,,0'' dargestellt:
> as.integer(mdy.date(1,1,1960))
[1] 0
> as.integer(mdy.date(1,2,1960))
[1] 1
> 

20  Anhang

20.1  Hinweise für R unter Linux

20.1.1  Installation

Das Basisprogramm wird für einige Linux-Distributionen in fertig kompilierter Form angeboten . Die Installation wird am Shell-Prompt mit den Kommandos7
 sudo apt-get install r-base 
 sudo apt-get install r-recommended 

ausgelöst.
Zur Installation von Pakete besorgt man sich von der CRAN-Webseite die entsprechenden Quellcodedateien (.tar.gz) und installiert am Shell-Prompt (z.B. combinat_0.0-6.tar.gz)
   R CMD INSTALL combinat_0.0-6.tar.gz

was funktioniert, wenn sich die notwendigen Entwicklungswerkzeuge einschließlich gcc und Fortran-Compiler auf dem Linux-System befinden. Außerdem sollten sich die Bibliotheken an der Stelle nach einer typischen Installation befinden. Eine alternative Methode vom R-Prompt aus:
   install.packages("Paketname")

Danach wird das Paket Paketname und alle Pakete installiert von denen Paketname abhängig ist.

20.1.2  R konfigurieren

Das Verhalten von R kann durch den Befehl options() beeinflußt werden, dessen Argument eine Liste von Zuweisungen im Format ,,variable=wert'' enthält.Will man beispielsweise einen anderen Browser (SeaMonkey) für die Anzeige der Hilfedateien definieren, so kann das (Beispiel für Linux) unter Verwendung des nach chromium mit
  options(browser="/usr/bin/chromium-browser") 

,,von Hand'' geschehen, während R läuft. Wenn man dagegen eine Konfigurationsdatei anlegen will, um dies vor dem Start des Programms einzutragen, kann das in Rprofile.site im etc-Unterverzeichnis geschehen. Weitere Optionen zu Konfigurationsdateien sind im Abschnitt ,,Customizing the environment'' im Kapitel ,,Writing your own functions'' des Begleitdokuments ,,An introduction to R'' beschrieben.

20.1.3  PDF-, PostScript- und EPS-Dateien von Abbildungen erstellen.

Unter Windows kann eine Grafikdatei mit dem Menü des Grafikfensters gespeichert werden. Um eine EPS-Datei mit der Linux-Implementation von R zu erstellen, wird die Grafik im Grafikfenster erzeugt mit einem dazu geeigneten Befehl, dann am R-Prompt
   dev.copy2eps()

eingegeben. Es wird dann eine Datei mit dem Namen Rplot.eps angelegt. Um eine PostScript-Datei (Name: foo.ps) zu erzeugen, ist vor dem Aufruf des Bildes
   postscript("foo.ps")

einzugeben, das Bild mit dem geeigneten Aufruf zu erzeugen und anschließend mit
   dev.off()

der PostScript-Ausgabeprozeß zu schließen. Ähnlich kann eine Grafik in eine PDF-Datei (aus.pdf) geschrieben werden:
  pdf("aus.pdf")

Befehle eingeben, um die PDF-Datei zu erzeugen, mit
   dev.off()

den Ausgabeprozeß schließen.

20.2  Allgemeine Befehle

Der Befehl library() zeigt die Liste der verfügbaren Bibliotheken an, mit library(MASS) wird die Library MASS geladen. Mit data() wird die Liste der Datensätze angezeigt, data(geyser) lädt und geyser zeigt die Daten zu geyser.
Ermitteln des aktuellen Arbeitsverzeichnisses: getwd(), wechseln des aktuellen Verzeichnisses: setwd("LW:/verzeichnis"). Mit list.files() werden die Dateien im aktuellen Verzeichnis angezeigt.
Es empfiehlt sich bei der Arbeit mit R, den Quellcode im Texteditor zu bearbeiten und zum Ausführen den abgespeicherten Quellcode auszuführen: source("scatter1.r"). Wenn der auzuführende Code ausgedruckt werden soll, geschieht das mit source("scatter1.r", echo=T). Wenn der ausgedruckte Quellcode ohne Prompt erscheinen soll, geben Sie bitte source("scatter1.r", echo=T,prompt.echo="") ein.

20.3  Einstellen von Optionen des Systems

Beim Start ist die Anzeige der ,,nackten'' Hilfedatein etwas unkomfortabel. Die ,,Compiled-HTML-Hilfe'' kann als Vorgabe eingestellt werden mit:
options(help_type="html")

Eine Option kann dann abgefragt werden mit z. B.:
getOption("help_type")
[1] "html"

Wenn die Genauigkeit des Systems bei der Ausgabe von Resultaten geändert werden soll, kann das mit
options(digits=20)

geschehen.

20.4  Textdarstellung von R-Objekten als Textdatei speichern und wieder einlesen

Die Datei morley.tab werde eingelesen mit
mm <- read.table("morley.tab")

mit mm können dann die Daten angesehen werden. Der Vektor
a <- c(1, 2, 3)

und mm sollen in eine Textdatellung von R-Objekten geschrieben werden:
dump(c("mm","a"), file = "mm.dat")

Mit
source("mm.dat")

werden dann beide Objekte wieder eingelesen.

20.5  Datendateien für R formatieren

Das folgende awk-Skript in Abschnitt 20.6.1 erlaubt die Umwandlung einer Datendatei in das Format für R (es wurde für gawk, die GNU-Implementation von awk geschrieben).

20.6  Quellcodes

20.6.1  ToR.awk

BEGIN {
  i = 1
}

{
  a = $0
  if (i == 1)
  {
       printf("      %s\n", a)
  }
  else if (i > 1)
  {
     if (length(a) > 0)
     {
       printf("%-4i  %s\n",i-1, a)
     }
  }
  i++
}

Der Aufruf schreibt den Inhalt von input.txt formatiert in out.dat.
gawk -f ToR.awk input.txt > out.dat

benutzt werden.

20.6.2  Perc.R

#
# perc(arr, pc.wert) returns the `pc.wert's percentile of the data
# in the vecctor `arr'
# Reference: Reed et al., Clinical Chemistry 1971:17(4);275-84
#
perc <- function(arr, pc.wert) {
   neu <- arr
   neu <- sort(neu)
   n <- length(neu)
   exakt.perz <- (n+1)*pc.wert/100
   hilfswert <- floor(exakt.perz);
   untergr <- neu[hilfswert];
   obergr <- neu[hilfswert + 1];
   if ((hilfswert < 1) || ((hilfswert+1) > n))
   {
      print("Percentile is out of range");
      return(invisible())
   }
   perzentil <- untergr + (obergr - untergr)*(exakt.perz - floor(exakt.perz))
   return(perzentil)
}


21  Versionen

04.03.2018: Abschnitt 1 eingefügt, Abschnitt 20.1 gekürzt und aktualisiert, Abschnitt 14: R-Code zum zweiten Beispiel aktualisiert.
05.02.2021: Abschnitt 1 ergänzt, Abschnitt 2.1 erweitert, Abschitt 11: die Daten aus [7,Seite 234] wurden eingefügt. In Abschnitt 4.2 wurde Kendalls Rangkoeffizient eingefügt.
07.02.2021 Abschnitt 20.3: options(htmlhelp=T) geändert in options(help_type="html"), Abschnitt 4.1 ergänzt.
07.03.2021 G-Test (Abschnitt 5.2) eingefügt. Den Befehl install.packages("Paketname") in Abschnitt 20.1.1 aufgenommen.
25.04.2021 Verfahren zur Untersuchung multipler Vergleiche zwischen einzelnen Gruppen nach signifikantem H-Test (ConoverTest()) eingefügt: Abschnitt 13.2

References

[1]
An Introduction to R. http://cran.r-project.org/doc/manuals/R-intro.html.
[2]
Dalgaard P. Introductory Statistics with R. Springer, New York, Berlin, Heidelberg, Hong Kong, London, Milan, Paris, Tokyo, 2002.
[3]
Maindonald J & Braun J, Hg. Data analysis and graphics using R - an example-based approach. Cambridge University press, Cambridge, 2003.
[4]
Reed AH, Berry RJ, & Mason WB. Influence of statistical method on the resulting estimate of normal range. Clinical Chemistry 17(4):274-284, 1971.
[5]
Sachs L & Hedderich J. Angewandte Statistik. Springer, Dordrecht, Heidelberg, London, New York, 13. Aufl., 2009.
[6]
Bortz J, Lienert GA, & Boehnke K, Hg. Verteilungsfreie Methoden in der Biostatistik. Springer-Verlag, Berlin, 1990.
[7]
Sachs L. Angewandte Statistik. Springer, Berlin, Heidelberg, New York, Tokyo, 6. Aufl., 1984.
[8]
Weber E. Grundriß der biologischen Statistik. Gustav Fischer Verlag, Stuttgart, New York, 8. Aufl., 1980.
[9]
Sachs L & Hedderich J, Hg. Angewandte Statistik. Methodensammlung mit R. Springer, Berlin, Heidelberg, New York, 12. Aufl., 2006.
[10]
Storm R. Wahrscheinlichkeitsrechnung, mathematische Statistik und statistische Qualitätskontrolle. Fachbuchverlag, Leipzig, Köln, 1995.
[11]
Hartung J, Elpelt B, & Klösener KH. Statistik. R. Oldenbourg, München, Wien, 8. Aufl., 1991.
[12]
Armitage P & Berry G. Statistical methods in medical research. Blackwell Scientific Publications, London, 3. Aufl., 1994.
[13]
Kiefel V, Santoso S, & Mueller-Eckhardt C. The Br(a)/Br(b) alloantigen system on human platelets. Blood 73:2219-2223, 1989.
[14]
Conover WJ, Hg. Practical nonparametric statistics. John Wiley & Sons, Inc., New York, Chichester, Weinheim, Brisbane, Singapore, Toronto, 3. Aufl., 1999.
[15]
Krause A & Olson M. Statistics and computing. Springer, New York, Berlin, Heidelberg, 2. Aufl., 2000.
[16]
Matthews DE & Farewell VT. Using and understanding medical statistics. Karger, Basel, 2. Aufl., 1988.
[17]
Matthews DE & Farewell VT. Using and understanding medical statistics. Karger, Basel, 5. Aufl., 2015.
[18]
Henry DA, Carless PA, Moxey AJ, O'Connell D, Forgie MA, Wells PS, & Fergusson D. Pre-operative autologous donation for minimising perioperative allogeneic blood transfusion. Cochrane database of systematic reviews: CD003602, 2001.

Index (showing section)


Arbeitsverzeichnis
     Wechsel, 20.2

Bartlett Test, 7.2
Boxplot, 18.3
     logarithmisch unterteilte y-Achse, 18.3
Browser für Hilfetexte ändern, 20.1

Chiqudadrat-Test
     Kontingenztafeln, 5.1
Cohens Kappa, 4.1
Conover, Einzelvergleiche, 13.2

Datei
     Daten einlesen, 3.0
Daten
     Differenz zwischen zwei, 19.2
Daten aus einer Datei einlesen, 3.0
Datumsberechnungen, 19.2
Determinate einer Matrix, 19.1
Diagramme, 18.0

Eingabe Beispiele, 1.0

Fishers exakter Test, 5.4
Friedman-Test, 12.0, 18.6

G-Test, 5.2
Genotyp-Häufigkeiten, 8.3
Goodness of fit-Tests, 8.0
Grafiken, 18.0

H-Test, 13.1
Hardy-Weinberg-Gleichweicht, 8.3
Histogramm, 2.1

interaction.plot(), 18.6

Kaplan Meier-Kurve, 14.2
Kendalls Rangkorrelationskoefizient, 4.2
Kolmogorov-Smirnov Test, 8.1
Konfidenzintervall
     relative Häufigkeiten, 6.0
Konfigurieren von R, 20.1
Kruskal-Wallis-Test, 13.1

Linux
     Grafikdateien erstellen, 20.1
     Installation unter, 20.1
logarithmisch unterteilte y-Achse
     Boxplot, 18.3

Median, 2.2
Metaanalyse, 17.0
Mittelwert, 2.2
multiple Vergleiche nach H-Test, 13.2

Odds Ratio, 5.5
Optionen von R einstellen, 20.3

Perzentilen, 2.1

Quantil, 2.1

Rangkorrelationskoefizient, 4.2
read.table(), typisches Anwendungsbeispiel (Bartlett Test), 7.2
Regression
     lineare, 3.0
Relative Häufigkeiten
     Konfidenzintervall, 6.0

Scatterplot, 18.4
Shapiro-Wilk-Test, 8.2
Spearmans Rangkorrelationskoefizient, 4.2
Standardabweichung, 2.2
Stichprobengröße
     Bestimmung, 16.0
         Vergleich zweier Mittelwerte, 16.1
         Vergleich zweier relativer Häufigkeiten, 16.2
stripchart(), 18.5
stripplot(), 18.5
Säulendiagramm, 18.1

t-Test
     abhängige Stichproben, 10.0
     unabhängige Stichproben, 9.0

Übereinstimmung der Beurteilung, 4.0
Überlebenszeitdaten, 14.0
     Kaplan Meier-Kurve, 14.2

Varianzanalyse
     einfache, 7.1
Verteilungen, statistische, 15.0
     Chiquadrat-Verteilung, 15.1
     F-Verteilung, 15.2
     Standardnormalverteilung, 15.4
     t-Verteilung, 15.3
Verzeichnis
     Wechsel, 20.2

Footnotes:

1frei verfügbar unter http://cran.r-project.org/
2Die genaue Beschreibung der verwendeten Methoden finden sich in der erweiterten Dokumentation der Webseite https://www.rdocumentation.org/
3bei rho=0 wird der Log-Rank oder Mantel-Haenszel Test, bei rho=1 die PETO & PETO Modifikation des GEHAN-WILCOXON-Tests verwendet
4üblicherweise: 0=noch lebend, 1: verstorben (Ereignis eingetroffen)
5n.trt: ,,n treated'', Anzahl der mit autologer Spende ,,behandelten'' Patienten, n.ctrl, Anzahl der Patienten in der Kontrollgruppe, tr.trt: Anzahl der Patienten mit Fremdbluttransfusionen in der Gruppe mit autologer präoperativer Blutspende, tr.ctrl: Anzahl der Patienten mit Fremdbluttransfusionen in der Kontrollgruppe
6meta.DSL für Random effects (DerSimonian-Laird) meta-analysis
7hier beschrieben am Beispiel Ubuntu


File translated from TEX by TTH, version 4.15.
On 25 Apr 2021, 22:58.