Rachunek Prawdopodobieństwa i Statystyka lab 6. Kaja Gutowska (Kaja.Gutowska@cs.put.poznan.pl) R umożliwia używanie wielu wyspecjalizowanych, mniej lub bardziej popularnych funkcji matematycznych i statystycznych. Przedstawione zostaną wybrane z nich. 1. Wybrane funkcje matematyczne 1.1 Wielomiany: Pakiet polynom zawiera funkcje do tworzenia i operowania na wielomianach. - Zdefiniowanie dwóch przykładowych wielomianów: > (p1 <- polynomial(c(2,0,1))) # 2 + x^2 > (p2 <- polynomial(c(2,2,1,1))) # 2 + 2*x + x^2 + x^3 - Wielomiany można dodawać/odejmować/mnożyć/dzielić używając standardowych operatorów: > p1 + p2 # 4 + 2*x + 2*x^2 + x^3 > p1 * p2 # 4 + 4*x + 4*x^2 + 4*x^3 + x^4 + x^5 - Wielomiany można całkować i różniczkować: > integral(p1,c(0,1)) # [1] 2.333333 > deriv(p2) # 2 + 2*x + 3*x^2 - Można wyznaczyć najmniejszą wspólną wielokrotność i największy wspólny dzielnik > LCM(p1,p2) # 2 + 2*x + x^2 + x^3 > GCD(p1,p2) # 2 + x^2 - Wybrane funkcje z pakietu polynom: polynomial(wsp) - ta funkcja pozwala zbudować wielomian przez podanie współczynników tego wielomianu. Współczynniki określa wektor wsp, pierwszy element tego wektora to wyraz wolny, kolejny wraz przy elemencie liniowym itp. integral(pol,lim) - ta funkcja wyznacza całkę z wielomianu pol w granicach lim. deriv(pol) - ta funkcja wyznacza pochodną wielomianu pol. poly.calc(x), poly.calc(x,y) - ta funkcja wyznacza wielomian o możliwie najmniejszym stopniu, o zerach w punktach x (jeżeli podany będzie tylko jeden argument) lub wielomian przechodzący przez punkty x,y (jeżeli podane będą dwa argumenty). GCD(pol1, pol2) wielomianów. - ta funkcja wyznacza największy wspólny dzielnik dwóch LCM(pol1, pol2) - ta funkcja wyznacza najmniejszą wspólną wielokrotność. solve(pol), polyroot(pol) -ta funkcja wyznacza zera danego wielomianu (działa również dla wielomianów zespolonych).
1.2 Operacje na zbiorach: Pakiet base zawiera funkcje do operowania na zbiorach. Zbiory reprezentowane są jako wektory. - Zdefiniowanie dwóch przykładowych zbiorów: > x <- 1:10 > y <- 5:15 - Na zbiorach można wykonać różnicę symetryczną (operacja XOR), czyli suma zbiorów minus część wspólna zbiorów: > setdiff(union(x,y), intersect(x,y)) # [1] 1 2 3 4 11 12 13 14 15 - Sprawdzenie czy zbiory są sobie równe: > setequal(x, y) - Sprawdzenie czy dany element należy do zbioru: > is.element(3, x) - Wybrane funkcje z pakietu base: union(x, y) - wynikiem tej funkcji jest suma zbiorów x i y. intersect(x, y) - wynikiem tej funkcji jest część wspólna zbiorów x i y. setdiff(x, y) - wynikiem tej funkcji jest różnica zbiór x minus y. Różnica zbiorów jest funkcją niesymetryczną. setequal(x, y) - wynikiem tej funkcji jest wartość logiczna, równa TRUE, gdy zawartości obu zbiorów są sobie równe. is.element(el, set) - wynikiem tej funkcji jest wartość logiczna, równa TRUE, gdy element el należy do zbioru set. 1.3 Rachunek różniczkowo-całkowy: Operacje różniczkowania są związane z funkcjami D() i deriv() z pakietu stats. Obie funkcje zwracają ten sam wynik, ale mają inny sposób podawania argumentów. - funkcja D(), potrzebuje argumentu expression, - funkcja deriv(), jako argument przyjmuje formułę bez określonej lewej strony Operacje całkowania funkcja integrate(), która wyznacza całkę na zadanym, niekoniecznie skończonym przedziale. > integrate(function(x) sin(x)^2, 0, 600)
2. Wybrane funkcje statystyczne 2.1 Liczbowe statystyki opisowe: -Załącz dane z poprzednich zajęć (dane.csv), celem przetestowania wybranych funkcji: dane <- read.csv("http://www.cs.put.poznan.pl/kgutowska/rpis/dane/dane.csv", sep = ";") attach(dane) - Wybrane funkcje: > range(wiek) > median(wiek) > cor(dane [,c(1,6,7)]) > IQR(wiek) > kurtosis(wiek) > mean(wiek) > mad(wiek) > mean(wiek, trim=0.2) > quantile(wiek, c(0.1, 0.25, 0.5, 0.75, 0.9)) > geometric.mean(wiek) > sd(wiek) > harmonic.mean(wiek) > skewness(wiek) Opis powyżej zastosowanych funkcji (w nawiasach potrzebne pakiety): - max(base) - wartość maksymalna w próbie - min(base) wartość minimalna w próbie - mean(stats) - średnia arytmetyczna. Nieobowiązkowym argumentem tej funkcji jest trim. Jeżeli wartość tego argumentu jest różna od zera, to wyznaczona średnia jest ucięta (Windsordzka). Średnią uciętą wyznacza się jak arytmetyczną, po usunięciu 200% * trim skrajnych obserwacji. - weighted.mean(stats) - średnia ważona. Drugim argumentem funkcji jest wektor wag. - geometric.mean(psych) - średnia geometryczna - harmonic.mean(psych) - średnia harmoniczna - median(stats) - mediana (wartość środkowa) - quantile(stats) - kwantyl wybranego rzędu. Drugim argumentem funkcji quantile() jest wektor kwantyli do wyznaczenia. W tej funkcji zaimplementowano 9 różnych algorytmów do wyznaczenia kwantyli w różny sposób obsługujących sytuację, gdy wartość kwantyla wypada między obserwacjami. Metodę wyznaczania kwantyli określa się argumentem type. - range (base) - przedział zmienności próby. - IQR(stats) - rozstęp międzykwartylowy, czyli różnica między górnym, a dolnym kwartylem. - var(stats) - wariancja w próbie. Wyznaczony jest nieobciążony stymulator wariancji. Jeżeli podane zostaną dwa wektory o różnej długości, to funkcja var() wyznaczy kowariancję pomiędzy tymi wektorami. - ad(stats) - odchylenie standardowe. - cor(stats), cov(stats) - macierz korelacji kowariancji. Argumentami może być para wektorów lub macierz. Dla macierzy korelacje i kowariancje wyznaczone będą dla wszystkich par kolumn. - mad(stats) - medianowe odchylenie bezwzględne. - ad(stats)/mean(stats) - współczynnik zmienności CV, czyli odchylenie standardowe podzielone przez średnią z próby. - length(base) - liczba elementów w próbie.
- kurtosis(e1071) - kurtoza miara koncentracji (spłaszczenia). Rozkład normalny ma kurtozę równą 0. - skewness(e1071) - skośność, miara symetryczności. Rozkład symetryczny ma skośność = 0. - moda(drop) - moda lub dominanta, czyli wartość występująca najczęściej w próbie. Podsumowanie wartości wektora, macierzy lub ramki danych używając funkcji summary(). Funkcja ta wyświetla proste podsumowanie wektora obserwacji: - w przypadku zmiennej jakościowej, występującej na kilku poziomach, pokaże liczebność obserwacji w każdym z możliwych poziomów, - w przypadku zmiennej ilościowej, pokaże wektor z wartościami: min, max, mediany, kwartyli pierwszego i trzeciego: > summary(wyksztalcenie) > summary(wiek) - Tablice kontyngencji, czyli funkcja table(base) Ta funkcja wyznacza tablice kontyngencji jednej lub większej liczby zmiennych wyliczeniowych. Poza funkcją table, można wykorzystać xtabs() lub ftable() > table(wyksztalcenie, praca) 2.2 Graficzne statystyki opisowe: - Histogram, funkcja (hist) pojawiła się na wcześniejszych zajęciach. Histogram przedstawia liczebności obiektów w poszczególnych przedziałach danej zmiennej. Innymi słowy, obiekt klasy histogram przechowuje informacje o wyznaczonych liczebnościach i częstościach. Poniżej, dwa przykładowe wywołania funkcji hist(): > hist(wiek, 5, main = "Histogram zmiennej wiek", ylab = "liczebnosci") > rug(wiek, side = 1, ticksize = 0.03, col = "red") > h = hist(wiek, 20, main = "Histogram zmiennej wiek", ylab = "liczebnosci") > rug(jitter(wiek, factor = 2), side = 1, ticksize = 0.03, col = "red") > str(h) - Wykres pudełkowy, boxplot(graphics). Jest to popularna metoda prezentacji zmienności pojedynczej zmiennej. Jednak można go wyznaczyć dla kilku zmiennych, co pozwala na porównywanie rozkładów zmiennych. Boxplot rysuje tzw. pudełko z wąsami za odstające uznaje się te obserwacje, które odstają od pudełka. Dodatkowo, jako argument można podać wektor wartości lub listę wektorów wartości. - Jeżeli argumentem będzie jeden wektor to narysowane będzie jedno pudełko. - Jeżeli argumentem będzie klika wektorów liczb to narysowanych będzie kilka pudełek. - Jeżeli argumentem będzie formuła opisująca zależność między zmienną ilościową a zmienną jakościową, to narysowane będzie pudełko dla każdego poziomu zmiennej jakościowej.
Boxplot 1 zmiennej i chmura punktów, przedstawiająca obserwacje: > boxplot(wiek) > tmpx = jitter(rep(1.3,length(wiek)), factor = 3) > points(tmpx, wiek, pch=16, col="black") > points(tmpx, wiek, pch=16, col = "lightgrey", cex=0.5) Boxplot 2 zmiennych (rozbicie na podpopulacje): > boxplot(wiek ~ wyksztalcenie, data = dane, col = "lightgrey") > table(wyksztalcenie, wiek) - Wykres rozrzutu, scatterplot() / sp(). Wykres rozproszenia, pozwala na przedstawienie zależności pomiędzy parą zmiennych. Do wykresu rozrzutu można dorysować prostą regresji liniowej, krzywą regresji nieparametrycznej. Wykres rozrzutu pozwala zaobserwować zależności pomiędzy badanymi zmiennymi, można zaobserwować czy ta zależność jest taka sama czy różna w podpopulacjach. >sp(cisnienie.skurczowe, cisnienie.rozkurczowe, gropus=plec, smooth=f, lwd=3, pch=c(20,21), cex=1.5) >sp(cisnienie.skurczowe, cisnienie.rozkurczowe, smooth=f, reg.line=f) Proszę zajrzeć na stronę: https://www.statmethods.net/graphs/scatterplot.html - Rozkłady zmiennych losowych (jednowymiarowych). Nazewnictwo funkcji związanych ze zmiennymi losowymi jest zestandaryzowane. Nazwy funkcji składają z dwóch członów: [prefix] [nazwa.rodziny.rozkładów]() > runif(5) # losujemy 5 liczb z rozkładu jednostajnego > punif(0.5) # wyznaczamy wartość dystrybuanty w punkcie 0.5 > dunif(0.5) # wyznaczamy wartość gęstości rozkładu w punkcie 0.5 > qunif(0.1) # Wyznaczamy wartość kwantyla rzędu 0.1 Suffix - nazwa.rodziny.rozkładów określa jakiej rodziny rozkładów dana funkcja dotyczy. Prefix oznaczony przez jedną z liter: r, p, d, q. r random rozpoczyna nazwę funkcji generatora liczb losowych. Funkcja taka generuje próbę o liczebności n. p probability - rozpoczyna nazwę funkcji wyznaczającej wartości dystrybuanty danego rozkładu w punktach określony przez wektor x. d density - rozpoczyna nazwę funkcji wyznaczającej gęstości dla rozkładów ciągłych lub prawdopodobieństwa dla rozkładów dyskretnych danego rozkładu w punktach określony przez wektor x. q quantile - rozpoczyna nazwę funkcji wyznaczającej wartości kwantyli danego rozkładu w punktach q.
- Rozkład normalny / rozkład Gaussa: Wybieramy punkty, w których wyznaczamy gęstość i dystrybuantę: > x <- seq(-4,4, by=0.1) > plot(x, dnorm(x), type="l", lwd=3, cex.axis=1.5, cex.lab=1.5) Dorysowanie dystrybuanty wymaga użycia innej osi OY, dlatego zmieniamy współrzędne w wyświetlanym oknie graficznym. Oś Y przyjmie wartości od -0.04 do 1.04, po utworzeniu nowego układu, dorysowujemy dystrybuantę: > par(usr=c(-4,4,-0.04,1.04)) > lines(x, pnorm(x), lty=2, lwd=3, cex.axis=1.5, cex.lab=1.5) Dodajemy oś OY po prawej stronie > axis(side=4, cex.axis=1.5, cex.lab=1.5) > mtext(side=4, "pnorm()", line=2.5, cex.axis=1.5, cex=1.5) Funkcje z pakietu stats do generowania liczb i wyznaczania charakterystyk rozkładu normalnego to pnorm(), dnorm(), qnorm(), rnorm(). Proszę zapoznać się w wymienionymi funkcjami, zobaczyć w helpie ich deklaracje. > dnorm(-1:1,,mean=0, sd=1) wartości gęstości rozkładu normalnego w punktach - 1, 0, 1. Powyższe funkcje można wykorzystać np. do wylosowania liczb (10) z rozkładu normalnego o zadanej średniej (2) i odchyleniu standardowym (1): > rnorm(10, mean=2, sd=1) co więcej, zarówna średnia jak i odchylenie mogą być wektorami > rnorm(10, mean=1:10, sd=1:10) Przykładowe zastosowanie powyższych funkcji: > x=runif(100) # wartości losowe z przedziału jednostajnego [0,1] > hist(x, probability=true) > curve(dunif(x,0,1), add=t) # dunif wartość gestości rozkładu > x=rnorm(100) # wartości losowe z rozkładu normalnego > hist(x, probability=true, col=gray(.9)) > curve(dnorm(x), add=t) # wartości gęstości rozkładu normalnego - Testowanie zgodności z rozkładem normalnym: Jest wiele testów, a wybór testu zależy od tego jakich odstępstw od normalności można się spodziewać lub tego przed jakimi odstępstwami chcemy się uchronić. Losujemy próbkę z rozkładu normalnego o parametrach 5 i 1, a następnie wykonujemy test Shapiro-Wilka: > set.seed(100) > rozklad_n <- rnorm(100, mean=5, sd=1) > shapiro.test(rozklad_n) Ponieważ p-value nie jest mniejsze niż 0.05 (p>0.05), nie odrzycamy hipotezy zerowej o rozkładzie normalnym.
Do wizualnej oceny normalności można utworzyć wykres: > hist(rozklad_n, probability=true, col=gray(.9)) > x<-rozklad_n > curve(dnorm(x,mean=5, sd=1),add=t) Inny przykład, losujemy próbkę z rozkładu jednostajnego, a następnie wykonujemy test Shapiro-Wilka: > set.seed(100) > inny_rozklad <- runif(100) > hapiro.test(inny_rozklad) Jako, że p-value < 0.05 to odrzucamy hipotezę, że rozkład jest normalny. Utwórzymy odpowiedni wykres: > hist(inny_rozklad, probability=true, col=gray(.9)) > x<-inny_rozklad > curve(dunif(x),add=t) Prosta instrukcja na przypisane wartości pvalue bezpośrednio podczas działania testu: > (pvalue <- shapiro.test(inny_rozklad)$p.value) - Przykładowe testy statystyczne: 1. Test t-studenta dla jednej próby - test parametryczny używany do sprawdzania czy wyniki pochodzą z populacji o danej średniej. > set.seed(100) > x <- rnorm(50, mean = 10, sd = 0.5) > t.test(x, mu=10) W powyższym przypadku p-value jest nie mniejsza niż 0,05. Dlatego hipoteza zerowa, że średnia = 10, nie może zostać odrzucona. Należy również zauważyć, że 95% zakresu przedziału ufności obejmuje wartość 10. Można więc powiedzieć, że średnia "x" wynosi 10, zwłaszcza że zakłada się, że "x" ma rozkład normalny. W przypadku, gdy nie zakłada się normalnego rozkładu, użwa się innego testu (Wilcoxona). Sprawdź argument mu, co to za wartość? Jaki jest wynik z zastosowaniem wartości domyślnej? 2. Test Wilcoxona - nieparametryczna metoda używana do testowania, czy oszacowanie różni się od jego prawdziwej wartości. Test Wilcoxona może być alternatywą dla testu t-studenta, zwłaszcza gdy zakłada się, że próbka nie charakteryzuje się rozkładem normalnym. > wektor <- c(1.83, 0.50, 1.62, 2.48, 1.68, 1.88, 1.55, 3.06, 1.30) > wilcox.test(wektor) Jeśli wartość p<0,05, odrzuć hipotezę zerową.
3. t-test dla dla dwóch prób: > t.test(1:10, y = c(7:20)) Przy wartości p<0,05 możemy bezpiecznie odrzucić hipotezę zerową, że nie ma różnicy w średniej. 4. Test Wilcoxona dla dwóch prób: > a <- c(0.80, 0.83, 1.89, 1.04, 1.45, 1.38, 1.91, 1.64, 0.73, 1.46) > b <- c(1.15, 0.88, 0.90, 0.74, 1.21) > wilcox.test(a,b) Przy wartości p>0.05 nie możemy odrzucić hipotezy zerowej, że zarówno x i y mają taką samą średnią. 5. Korelacja - służy do przetestowania liniowej zależność dwóch zmiennych. Oblicza się korelację między dwiema zmiennymi ciągłymi i sprawdza, czy y jest zależne od x. > cor.test(cars$speed, cars$dist) # skorzystaj z gotowego pakietu. Jeśli p-value jest mniejsza niż 0.05, odrzucamy hipotezę zerową, że prawdziwa korelacja wynosi zero (tj. zmienne są niezależne); dochodzimy do wniosku, że dystans zależy od prędkości. - Wstępne przetwarzanie danych: Często dane nie nadają się do bezpośredniego wykorzystania i zastosowania analiz statystycznych. Dane wymagają wstępnego przetwarzania. - Wybrane metody do radzenia sobie z brakującymi obserwacjami: Brakujące dane oznacza się NA, można wykorzystać funkcję is.na(). Chcąc usunąć brakujące dane z wektora, należy użyć funkcji na.omit() Natomiast chcąc usunąć brakujące dane z ramki, należy użyć funkcji complete.cases(). > w <- c(1,5,na,2,3,na,8,10,na,0,10,na) > is.na(w) # sprawdz czy są brakując dane > sum(is.na(w)) # suma brakujących danych > w <- na.omit(w) # usuń brakujące dane Usuwanie brakujących danych to najprostsze rozwiązanie, jednak nie jest najlepsze. Redukcja danych prowadzi do pogorszenia właściwości procedur statystycznych itp. Lepszym rozwiązaniem od usuwania jest wstawienie sztucznych pomiarów. Najczęściej wstawia się średnią, medianę. Jeszcze innym, lepszym rozwiązaniem, jest dopasowanie modelu regresji na zbiorze kompletnych danych. Wstawiając w miejsca brakujące wartości wyznaczone z modelu regresji. Zainstaluj pakiet Hmisc aby imputować wartości w miejsca brakujących obserwacji. > w2 <- c(1,5,na,2,3,na,8,10,na,0,10,na) > impute(w2, 3.5) # imputuj wartość 2.5 w miejsca NA > impute(w2, mean) # imputuj średnią
> impute(w2, "random") # imputuj randomowe wartości - Wybrane metody do wstępnej transformacji zmiennych: Najprostszą transformacją jest skalowanie, które polega na odjęciu od każdej obserwacji wartości średniej z próby i podzielenie tej różnicy przez odchylenie standardowe z próby. Transformacja może poprawiać wyniki. Aby wykonać skalowanie należy użyć funkcji scale(). Aby zdecydować czy dane mają być centrowane, trzeb ustawić parametr center=true co oznacza, że będzie odejmowana wartość średnia. Jeśli dane mają być skalowane, to parametr scale=true, co oznacza, że dane będą dzielone przez odchylenie standardowe. Wyznaczanie macierzy kowariancji dla 3 wybranych kolumn z danych dane.csv (załadowane na początku): > cov(dane[,c(1,6,7)]) Kowariancja danych znormalizowanych: > cov(scale(dane[,c(1,6,7)])) Wyznaczenie odchylenia standardowego dla wybranych kolumn; dzielimy wartości w kolumnach przez odchylenie standardowe. Do normalizacji można także wykorzystać funkcje sweep() i apply(): > wektor.sd <- apply(dane[,c(1,6,7)], 2, sd) > sweep(dane[,c(1,6,7)], 2, FUN="/",wektor.sd) Powyższe instrukcje można zastąpić jednym wywołaniem: > apply(dane[,c(1,6,7)], 2, function(x) x/sd(x)) 2.3 Wprowadzenie do analizy wariancji - Analiza jednoczynnikowa: http://www.sthda.com/english/wiki/one-way-anova-test-in-r - Analiza dwuczynnikowa: http://www.sthda.com/english/wiki/two-way-anova-test-in-r
Zadanie: Zadania pod koniec zajęć prześlij na maila (Kaja.Gutowska@cs.put.poznan.pl). Proszę nadać tytuł maila zgodnie z opisem: RPiS_Imię_Nazwisko_lab6 1. Utwórz skrypt R, w którym wykorzystasz dane dostępne na stronie: http://www.cs.put.poznan.pl/kgutowska/rpis.html Przygotuj odpowiedni format i załaduj dane do R. Dla kolumny o nazwie ex vitro, in vitro i transcript uzupełnij brakujące wiersze (od 3 do 926) wartością -999. Następnie zapisz do 3 plików tekstowych każdą z tych kolumn, dodaj indeksowanie. Przykładowo do pliku ex_vitro.txt, zawartość przedstawia się następująco: 1-999,000 2-999,000 3-999,000 4-999,000 5 0,075 6 0,000 7 0,049...