blatt10-loesung - Institut für Statistik

Transcrição

blatt10-loesung - Institut für Statistik
Übungsblatt 10 – Biostatistische Methoden
Ulrich Mansmann, Michael Höhle, Manuela Hummel
WiSe 2007/08
Übung: Dienstag 08.01.2008
In dieser Übung wird ein (bereits normalisierter) Genexpressionsdatensatz von Patienten mit akuter lymphoblastischer Leukämie (ALL) betrachtet. Es soll differentielle Expression untersucht werden zwischen Patienten
mit einer bei ALL häufig vorkommenden Mutation (BCR/ABL) und Patienten ohne diese Mutation.
Aufgabe 1 (Daten)
Laden Sie die Pakete affy, multtest, genefilter, limma und ALL. Laden Sie den Datensatz ALL.
(i) Wie viele Patienten enthält der Datensatz? Welche klinischen Informationen sind vorhanden? Um welchen
Microarray-Typen handelt es sich und wie viele Gene wurden gemessen?
> library(affy)
> library(multtest)
> library(limma)
> library(genefilter)
> library(ALL)
> data(ALL)
Der Datensatz enthält 128 Patienten. 21 klinische Parameter sind angegeben (Beschreibung der Variablen,
siehe ?ALL). Auf dem Affymetrix array hgu95av2 werden 12625 Gene gemessen.
> dims(ALL)
exprs
Features 12625
Samples
128
> names(pData(ALL))
[1] "cod"
"diagnosis"
"sex"
"age"
[5] "BT"
"remission"
"CR"
"date.cr"
[9] "t(4;11)"
"t(9;22)"
"cyto.normal"
"citog"
[13] "mol.biol"
"fusion protein" "mdr"
"kinet"
[17] "ccr"
"relapse"
"f.u"
"transplant"
[21] "date last seen"
> annotation(ALL)
[1] "hgu95av2"
(ii) Wählen Sie die Patienten mit B-Zellen ALL aus, die entweder die Mutation BCR/ABL oder gar keine
Mutation (’NEG’) tragen. Erzeugen Sie ein neues ExpressionSet mit den ausgewählten Patienten.
Aus der Variablen BT lässt sich schließen, ob eine B- oder T-Zellen ALL vorliegt. In mol.biol sind
vorliegende Mutationen angegeben.
> table(ALL$BT)
B B1 B2 B3 B4
T T1 T2 T3 T4
5 19 36 23 12
5
1 15 10
> table(ALL$mol.biol)
2
ALL1/AF4
BCR/ABL E2A/PBX1
10
37
5
NEG
NUP-98
p15/p16
74
1
1
> Subset <- intersect(grep("B", ALL$BT), which(ALL$mol.biol %in% c("BCR/ABL",
+
"NEG")))
> eset <- ALL[, Subset]
> table(eset$mol.biol)
ALL1/AF4
BCR/ABL E2A/PBX1
0
37
0
NEG
NUP-98
p15/p16
42
0
0
Aufgabe 2 (Differentielle Expression und Adjustierung)
Untersuchen Sie nun differentielle Expression zwischen BCR/ABL und NEG.
Wir brauchen nun oft die Matrix der Expressionswerte und eine Variable, die die Gruppenzugehörigkeit angibt.
Deshalb werden zunächst entsprechende Variablen erstellt.
> xx <- exprs(eset)
> group <- ifelse(eset$mol == "NEG", 0, 1)
(i) Ob ein Gen differentiell exprimiert ist kann mit einfachen Zweistichproben t-Tests entschieden werden.
Berechnen Sie mit Hilfe der Funktion rowttests() aus dem Paket genefilter t-Teststatistiken und ’rohe’
p-Werte für alle Gene.
Die Funktion rowttests() berechnet für alle Zeilen der Expressionsmatrix Zwei-Stichproben t-Tests (mit
gleichen Varianzen).
> ttests <- rowttests(xx, factor(group))
> str(ttests)
List of 4
$ statistic: num [1:12625] -0.737 -0.453
1.566
0.215
0.0658
0.533 ...
$ dm
: num [1:12625] -0.0430 -0.0321
0.0127
0.0318 ...
$ df
: num 77
$ p.value
: num [1:12625] 0.464 0.652 0.121 0.830 0.595 ...
> t.rawp <- ttests$p.value
> names(t.rawp) <- rownames(xx)
(ii) Führen Sie mit der Funktion p.adjust() Adjustierungen für multiples Testen nach den Methoden von
Bonferroni, Holm, Benjamini & Hochberg und Benjamini & Yekutieli durch. Zeichnen Sie die sortierten
adjustierten p-Werte p̃(j) der verschiedenen Methoden gegen die Anzahl der Hypothesen j (dafür kann
man z.B. die Funktion matplot() verwenden). Wie viele Gene haben nach Adjustierung gemäß Benjamini
& Yekutieli einen p-Wert < 0.01?
> my.methods <- c("none", "bonferroni", "holm", "BH", "BY")
> t.adjp <- sapply(my.methods, function(x) p.adjust(t.rawp, method = x))
> t.adjp[1:5, ]
none bonferroni holm
BH BY
1000_at
0.4636584
1
1 0.9185626
1
1001_at
0.6519879
1
1 0.9585758
1
1002_f_at 0.1214625
1
1 0.7022442
1
1003_s_at 0.8301676
1
1 0.9806216
1
1004_at
1
1 0.9506087
1
0.5954181
Die Funktion matplot() ermöglicht es, die Spalten einer Matrix einzeln darzustellen. Die p-Werte müssen
dafür sortiert werden. Abbildung 1 zeigt, dass die Adjustierungsverfahren, die die FWER (family-wise error
rate) kontrollieren (Bonferroni- und Holm-Korrektur), sehr konservativ sind. Die beiden FDR-Methoden
(false discovery rate) sind wie erwartet nicht so streng. Eine Adjustierung nach Benjamini & Yekutieli ist
konservativer als Benjamini & Hochberg. Bei Benjamini & Yekutieli sind auch Korrelationen zwischen den
Tests erlaubt.
> par(mfrow = c(1, 2))
> matplot(apply(t.adjp, 2, sort), type = "l", col = 1:5, lty = 1:5,
+
xlab = "number of hypotheses", ylab = "p-values")
> legend("bottomright", colnames(t.adjp), col = 1:5, lty = 1:5)
> matplot(apply(t.adjp, 2, sort)[1:100, ], type = "l", col = 1:5,
0.8
0.6
p−values
0
2000
4000
6000
8000
10000
12000
0.2
0.4
0.0
none
bonferroni
holm
BH
BY
0.0
0.2
0.4
p−values
0.6
0.8
1.0
lty = 1:5, xlab = "number of hypotheses", ylab = "p-values")
1.0
+
0
20
number of hypotheses
40
60
80
100
number of hypotheses
Abbildung 1: Adjustierte p-Werte der verschiedenen Verfahren versus Anzahl der Hypothesen; rechts: nur für
die ersten 100 Hypothesen.
Nach Adjustierung gemäß Benjamini & Yekutieli erhält man 19 signifikant differentiell exprimierte Gene.
> sum(t.adjp[, "BY"] < 0.01)
[1] 19
(iii) Erstellen Sie eine ’Topliste’ mit den adjustierten p-Werten der signifikanten Gene. Diese soll nach den
p-Werten sortiert sein.
> t.toplist <- sort(t.adjp[t.adjp[, "BY"] < 0.01, "BY"])
> str(t.toplist)
Named num [1:19] 4.76e-09 3.03e-08 1.03e-05 4.05e-05 1.33e-04 ...
- attr(*, "names")= chr [1:19] "1636_g_at" "39730_at" "1635_at" "1674_at" ...
Aufgabe 3 (Adjustierung mit Permutationstest)
Führen Sie einen Permutationstest (mit 1000 Permutationen) mit Adjustierung gemäß Westfall & Young durch.
(i) Im Paket multtest gibt es hierfür die Funktion mt.maxT(). Wie viele der so adjustierten p-Werte sind
< 0.01? Erstellen Sie wieder (mit Gennamen benannte) Vektoren der rohen und adjustierten p-Werte in
Originalsortierung (!) und eine Topliste der sortierten p-Werte der signifikanten Gene.
Mit der step-down Prozedur von Westfall & Young ergeben sich weniger signifikante Gene als zuvor. Dies
war zu erwarten, da die Methode von Westfall & Young die FWER kontrolliert, während die Benjamini
& Yekutieli Methode die weniger konservative FDR kontrolliert.
> set.seed(111)
> permut <- mt.maxT(xx, group, B = 1000)
> str(permut)
’data.frame’:
$ index
: num
12625 obs. of
714
9823
713
4 variables:
756 10604 ...
$ teststat: num
9.13 8.60 7.17 6.74 6.41 ...
$ rawp
: num
0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 0.001 ...
$ adjp
: num
0.001 0.001 0.001 0.001 0.001 0.001 0.002 0.003 0.003 0.003 ...
> sum(permut$adjp < 0.01)
[1] 16
Bei dieser Adjustierung werden die Gene nach den p-Werten sortiert. Die ursprüngliche Reihenfolge ist
aber in index gespeichert.
> ord <- order(permut$index)
> p.rawp <- permut$rawp[ord]
> names(p.rawp) <- rownames(xx)
> p.adjp <- permut$adjp[ord]
> names(p.adjp) <- rownames(xx)
> p.toplist <- sort(p.adjp[p.adjp < 0.01])
(ii) Vergleichen Sie die rohen und adjustierten p-Werte zwischen t-Tests und Permutationstest, indem Sie sie
gegeneinander plotten. Wieviele Gene kommen in beiden Toplisten vor?
Die rohen p-Werte beider Verfahren sind vergleichbar, siehe Abbildung 2. Im zweiten Plot sieht man, dass
die Prozedur von Westfall & Young konservativer ist als die Adjustierung nach Benjamini & Yekutieli.
Deshalb erweisen sich ja auch weniger Gene als hoch signifikant.
> par(mfrow = c(1, 2))
> plot(t.rawp, p.rawp, pch = ".", xlab = "raw t-test p-value", ylab = "raw permutation p-value")
> abline(a = 0, b = 1, col = 2)
> plot(t.adjp[, "BY"], p.adjp, pch = ".", xlab = "BY-adjusted t-test p-value",
+
ylab = "WY-adjusted permutation p-value")
> abline(a = 0, b = 1, col = 2)
Alle vom Permutationstest als signifikant erkannten Gene sind auch in der Topliste der t-Test-Prozedur.
> sum(names(t.toplist) %in% names(p.toplist))
[1] 16
Aufgabe 4 (Lineare Modelle, moderate t-Statistiken)
Führen Sie eine Analyse auf differentielle Genexpression mit dem Paket limma durch.
(i) Dazu muss zunächst eine passende Designmatrix erstellt werden. Dann werden mit lmFit() lineare Modelle
für jedes Gen berechnet und anschließend mit eBayes() ’stabilere’ Teststatistiken gewonnen.
Die Designmatrix und die linearen Modelle erstellt man wie folgt. Man erhält ein Objekt der Klasse
MArrayLM, das viele Informationen enthält.
> design <- model.matrix(~factor(group))
> design[1:5, ]
1.0
0.6
0.0
0.2
0.4
WY−adjusted permutation p−value
0.8
1.0
0.8
0.6
0.4
raw permutation p−value
0.2
0.0
0.0
0.2
0.4
0.6
0.8
1.0
0.0
raw t−test p−value
0.2
0.4
0.6
0.8
1.0
BY−adjusted t−test p−value
Abbildung 2: Links rohe, rechts adjustierte p-Werte der t-Test-Prozedur und des Permutationstests gegeneinander geplottet.
(Intercept) factor(group)1
1
1
1
2
1
0
3
1
1
4
1
0
5
1
0
> fit <- lmFit(eset, design)
> names(fit)
[1] "coefficients"
"rank"
"assign"
"qr"
[5] "df.residual"
"sigma"
"cov.coefficients" "stdev.unscaled"
[9] "pivot"
"genes"
"Amean"
"method"
[13] "design"
Die geschätzten Koeffizienten entsprechen denen von gewöhnlichen linearen Modellen.
> fit$coefficients[1:5, ]
(Intercept) factor(group)1
1000_at
7.495384
0.04296986
1001_at
4.996483
0.03208350
1002_f_at
3.902391
-0.06582929
1003_s_at
6.000954
-0.01270016
1004_at
5.841646
-0.03177045
> lm(xx[1, ] ~ group)
Call:
lm(formula = xx[1, ] ~ group)
Coefficients:
(Intercept)
group
7.49538
0.04297
Dann wird ein empirisches Bayes-Modell berechnet, um stabilere Schätzungen zu erhalten. Das Resultat
ist wieder eine Liste mit vielen Informationen.
> fit2 <- eBayes(fit)
> names(fit2)
[1] "coefficients"
"rank"
"assign"
[5] "df.residual"
"sigma"
"cov.coefficients" "stdev.unscaled"
"qr"
[9] "pivot"
"genes"
"Amean"
"method"
[13] "design"
"df.prior"
"s2.prior"
"var.prior"
[17] "proportion"
"s2.post"
"t"
"p.value"
[21] "lods"
"F"
"F.p.value"
(ii) Erstellen Sie mit topTable() eine Topliste der 10 ’besten’ Gene. Was wird dabei alles ausgegeben? Wie
viele Gene haben hier nach Adjustierung mit Benjamini & Yekutieli einen p-Wert < 0.01? Die rohen
und adjustierten p-Werte aller Gene sollen wieder in Vektoren gespeicherten werden; zudem wieder eine
Topliste, die nur die sortierten adjustierten p-Werte < 0.01 enthält.
Die Funktion topTable() gibt eine Topliste zusammen mit den wichtigsten Informationen in einer Tabelle
aus und führt zudem gleich eine Adjustierung für multiples Testen durch. Wichtig ist, dass man den
richtigen Koeffizienten von Interesse angibt, also hier coef = 2.
> tT <- topTable(fit2, coef = 2, number = 10, adjust = "BY")
> tT
ID
logFC
AveExpr
t
P.Value
adj.P.Val
B
714
1636_g_at 1.1000116 9.196420 9.386530 1.531812e-14 1.937914e-09 21.773880
9823
39730_at 1.1525269 9.000049 8.815214 2.028724e-13 1.283281e-08 19.443353
713
1635_at 1.2026753 7.897095 7.398075 1.208549e-10 5.096501e-06 13.636715
756
1674_at 1.4272115 5.001771 7.020362 6.486736e-10 2.051612e-05 12.102060
10604
40504_at 1.1810295 4.244478 6.683873 2.854764e-09 7.223193e-05 10.746992
10299
40202_at 1.7793784 8.621443 6.296601 1.536039e-08 2.874142e-04
9.206850
7082
37015_at 1.0327017 4.330511 6.288545 1.590294e-08 2.874142e-04
9.175072
2456
32434_at 1.6785501 4.466311 5.881601 9.015004e-08 1.425624e-03
7.586693
7094
37027_at 1.3487023 8.444161 5.749020 1.573117e-07 2.211300e-03
7.077075
9930
39837_s_at 0.4757069 7.144313 5.548352 3.621192e-07 4.581213e-03
6.314169
topTable() gibt neben den Gennamen und -Indizes, moderaten“ t-Teststatistiken und p-Werten zusätz”
lich die Werte AveExpr, logF C und B aus. AveExpr ist jeweils der mittlere (logarithmierte) Expressionswert eines Gens über alle samples. logF C ist der geschätzte Koeffizient und entspricht dem log2 -fold
change, d.h. logF C = log2 (mean(Gruppe2)/mean(Gruppe1)). Die vorliegenden
B ist der log-odds, dass ein Gen differentiell exprimiert ist. Der odds ist also exp(B) und die Wahrscheinlichkeit, dass ein Gen differentiell exprimiert ist exp(B)/(1 + exp(B)). Für das erste Gen aus tT gilt
z.B.
> B <- tT[, "B"]
> exp(B)/(1 + exp(B))
[1] 1.0000000 1.0000000 0.9999988 0.9999945 0.9999785 0.9998997 0.9998964 0.9994931
[9] 0.9991565 0.9981928
Nun erzeugen wir wieder Vektoren mit allen rohen und adjustierten p-Werten und eine Topliste der
adjustierten p-Werten der signifikanten Gene.
> l.rawp <- fit2$p.value[, 2]
> l.adjp <- p.adjust(l.rawp, method = "BY")
> sum(l.adjp < 0.01)
[1] 19
> l.toplist <- sort(l.adjp[l.adjp < 0.01])
(iii) Vergleichen Sie die rohen und adjustierten p-Werte und die Topliste mit den Ergebnissen des üblichen
t-Tests.
Im Vergleich zwischen t-Test- und limma-Methode findet man eine recht gute Übereinstimmung zwischen
den rohen p-Werten (die limma-Methode verwendet modifizierte t-Statistiken) und deshalb auch bei den
adjustierten (es wurde das gleiche Adjustierungsverfahren verwendet), siehe Abbildung 3. Die Toplisten
überschneiden sich komplett (davon kann man i.A. nicht ausgehen . . .).
> par(mfrow = c(1, 2))
> plot(t.rawp, l.rawp, pch = ".", xlab = "raw t-test p-values", ylab = "raw limma p-values")
> abline(a = 0, b = 1, col = 2)
> plot(t.adjp[, "BY"], l.adjp, pch = ".", xlab = "BY-adjusted t-test p-values",
+
ylab = "BY-adjusted limma p-values")
> abline(a = 0, b = 1, col = 2)
> sum(names(t.toplist) %in% names(l.toplist))
0.8
0.6
0.0
0.2
0.4
BY−adjusted limma p−values
0.6
0.4
0.0
0.2
raw limma p−values
0.8
1.0
1.0
[1] 19
0.0
0.2
0.4
0.6
0.8
1.0
0.0
0.2
raw t−test p−values
0.4
0.6
0.8
1.0
BY−adjusted t−test p−values
Abbildung 3: Links rohe, rechts adjustierte p-Werte der t-Test-Prozedur und der limma-Methode gegeneinander
geplottet.
Homepage:
http://www.stat.uni-muenchen.de/institut/ag/biostat/teaching/bm2007/
LaMo: 8. Januar 2008@