Rachunek Prawdopodobieństwa i Statystyka lab 7. Kaja Chmielewska (Kaja.Chmielewska@cs.put.poznan.pl) R umożliwia używanie wielu wyspecjalizowanych, mniej lub bardziej popularnych funckji 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 - Przekonwertuj wielomian na funkcję programu R, tak aby można było korzystać z obiektu jak ze zwykłej funkcji. Wyznacz jej wartości w kilku punktach. W pierwszym korku wykorzystaj pakiet orthopolynom, gdzie dostępne są bazy wielomianów. Wyznaczymy 5 pierwszych wielomianów Legendre a, za bazę wybieramy odcinek [0,1], a wielomiany chcemy mieć znormalizowane. > library("orthopolynom") > max <- 5 > (wielomiany <- slegendre.polynomials(max,normalized = TRUE)) Zdefiniuj wielomian jako funckję i wyznacz wartości. > wielomian4 <- as.function(wielomiany[[4]]) > wielomian4(c(0, 0.5, 1)) # [1] -2.645751 0 2.645751 Taką funkcję można wykorzystać do stworzenia wykresu: > curve(wielomian4, 0, 1, lwd=3, lty=4, ylab="")
- 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) - ta funkcja wyznacza największy wspólny dzielnik dwóch wielomianów. 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, setdiff(x, setdiff(y,x))) - 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 Maksimum, minimum i zero Często pewne problemy sprowadzają się szukania zer funkcji lub punktów minimalizujących lub maksymalizujących funkcję. Do tego celu można użyć funkcje optimize() /optimise() lub uniroot(). W obu przypadkach jeśli jest więcej niż jedno rozwiązanie, to wyznaczane jest dowolne. - optimize() wyznacza ekstrema, poniżej deklaracja funkcji: optimize(f, interval,..., lower = min(interval), upper = max(interval), maximum = FALSE, tol =.Machine$double.eps^0.25) - uniroot() wyznacza miejsca zerowe, poniżej deklaracja funkcji: uniroot(f,interval,...,lower=min(interval),upper=max(interval), f.lower = f(lower,...), f.upper = f(upper,...), tol =.Machine$double.eps^0.25, maxiter = 1000) Argumentami obu funkcji są: f czyli funkcja, dla której szukane mają być ekstrema/ miejsca zerowe, interval określający na jakim przedziale wyznaczane ma być ekstremum/miejsce zerowe. Dodatkowo, w funkcji optimize() można określić, czy poszukujemy maksimum czy minimum (argument maximum), a w funkcji uniroot() można wskazać maksymalną liczbę iteracji do wykonania (argument maxiter). Do badanej funkcji f można przekazać również dodatkowe argumenty. Przykład użycia, dla funkcji f(), szukamy minimum na przedziale [-1,10], określamy też dodatkowy argument dla funkcji czyli wyznacznik. f <- function(x, wyznacznik) {(x - 7)^wyznacznik - x} optimize(f, interval=c(-1,10), wyznacznik = 2) # $minimum [1] 7.5 # $objective [1] -7.25 - Inne funkcje służące do maksymalizacji funkcji: optim() i nlm(). Funkcja optim() może być wykorzystywana do optymalizacji po wielowymiarowym zbiorze. Natomiast funkcja optimize() dotyczy jednowymiarowego zbioru parametrów. 1.4 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/kchmielewska/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: - 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(wykształcenie, 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. >library(car) >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) Narysowanie 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. > qnorm(c(0.001, 0.025, 0.05, 0.5, 0.95, 0.975, 0.999)) - najpopularniejsze kwantyle rozkładu normalnego 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) 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 10 i 1.4, a następnie wykonujemy test Cramera-von Misesa (wymagany pakiet: nortest): > x <- rnorm(100, 10, 1.4) > cvm.test(x) > (pvalue <- cvm.test(x)$p.value) Do wizualnej oceny normalności można wykorzystać wykres kwantylowy dla rozkładu normalnego. Jeżeli obserwacje pochodzą z rozkładu normalnego to punkty układają się wzdłuż linii prostej (aby narysować linię trzeba wykorzystać funkcję qqline()) > y <- rnorm(100) > qqnorm(y) > qqline(y, col = "red") > qqplot(y) lub > qq.plot(y)
- 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.Chmielewska@cs.put.poznan.pl). Proszę nadać tytuł maila zgodnie z opisem: RPiS_Imię_Nazwisko_lab7 1. Znajdź miejsca zerowe wielomianu x3 3x2 x + 3. Znajdź najmniejszy wspólny dzielnik tego wielomianu i x3 12x2 x + 12. 2. Wróć do punktu 1.1. Wielomiany i narysuj ponownie wykres dla wielomian4, Następnie w pętli dorysuj pozostałe wielomiany. 3. Wróć do punktu 1.3 Maksimum, minimum i zero i zamiast funkcji optimize() użyj funkcji uniroot(), jaka jest różnica? 4. Napisz funkcję, która dla zadanego wektora liczb wyliczy średnią, wariancję, skośność i kurtozę. 5. W zbiorze danych (), znajduje się zmienna liczbowa Wiek i czynnikowa Receptory.estrogenowe. Narysuj wykres pudełkowy dla zmiennej Wiek w rozbiciu na zmienną Receptory.estrogenowe. Wykorzystaj funkcję vioplot, dzięki której narysujesz wykres skrzypcowy dla zmiennej Wiek w rozbiciu na poziomy zmiennej Niepowodzenia.