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@