1 Macierze
Macierze, podobnie jak wektory, mogą zawierać elementy dowolnego, ale tego samego typu (nie można utworzyć macierzy zawierającej jednocześnie np. wartości liczbowych i tekstowych).
Podstawowa polecenie służące tworzeniu macierzy to
matrix(vec, nrow=n, ncol=p, byrow=T)
,
gdzie vec
jest wektorem zawierającym kolejne elementy
macierzy, które standardowo będą rozmieszczone kolumnami. W celu
rozmieszczenia elementów wierszami należy wybrać opcję
byrow=T
.
1.1 Tworzenie macierzy
1.2 Wybrane operacje na macierzach
Przetestować działanie poniższych poleceń
x3=t(x2) |
#Transpozycja macierzy x2 |
b=x1*x2 |
#Iloczyn macierzy element po elemencie |
b=x3%*%x2 |
#Standardowy iloczyn macierzy |
dim(b) |
#Podaje wymiar macierzy |
b[3,2] |
#Wybranie elementu b32 macierzy b |
b[3,2]=5 |
#Przypisanie wartości do elementu macierzy |
b[,2] |
#Wybranie drugiej kolumny macierzy b |
b[c(3,4),] |
#Wybranie wiersza 3 i 4 macierzy b |
b[-2,] |
#Wybranie wszystkich wierszy macierzy b poza drugim
wierszem |
b[,-c(2,4)] |
#Wybranie wszystkich kolumn macierzy b poza drugą i
czwartą |
b[1,]>600 |
# Wykonanie testu na pierwszym wierszu macierzy |
ind=which(b[1,]>600) |
|
b[,ind] |
#Wybranie tych kolumn macierzy b , których pierwszy
elementjest większy niż 600 (jako wynik wcześniejszego polecenia) |
rbind(x1,x2) |
#Połączenie wierszowe macierzy, czyli utworzenie macierzy, której wierszami są kolejne wiersze macierzy x1 ,a następnie macierzy x2 . Polecenie to pozwala nadołączanie kolejnych wierszy do macierzy, efektem jest macierz postaci blokowej:\[ \left[ \begin{array}{c} x_1\\x_2 \end{array} \right] \] |
cbind(x1,x2) |
#Poziome, “kolumnowe” połączenie dwóch macierzy, czyli utworzenie
macierzy, w której (licząc od lewej) najpierw są kolumny macierzy
\[\left[ \begin{array}{c c} x_1 & x_2 \end{array} \right] \] |
apply(x1,2,sum) |
#Funkcja apply pozwala na zastosowanie funkcji
działającejna wektorach do macierzy x1 (w tym przypadku sumy)do kolumn (drugi argument jest tutaj równy 2) lub wierszy (drugi argument byłby równy 1). W wyniku dostajemy wektor zawierający sumy elementów poszczególnych kolumn macierzy x1 |
apply(x1,1,sum) |
#Jak wyżej, tylko tym razem otrzymujemy sumy elementów wierszami macierzy x1 |
apply(x1,1,max) |
#Otrzymujmy wektor zawierający element maksymalny każdego z wierszy macierzy x1 |
1.3 Zadania - macierze
1.3.1 Zadanie
Utworzyć wektor
x=(2;2;2;2;2)
za pomocą funkcjirep
oraz wektory=(-1;0;1;2;3)
za pomocą funkcjiseq
.Utworzyć macierz A o 5 wierszach i 2 kolumnach, w której pierwsza kolumna składa się z elementów wektora
x
a druga z elementów wektoray
.Zmienić drugi wiersz macierzy A na wiersz postaci (2;4)
1.3.2 Zadanie
- Utworzyć macierz
\(\mathbf{A}=\left( \begin{array}{ccc} 2&23&8\\10&6&90\\4&7&12\end{array}\right)\)
za pomocą poleceńcbind
i/lubmatrix
. Czy da się utworzyć tą macierz za pomocą poleceniarbind
? - Obliczyć średnią oraz iloczyn elementów w wierszach i kolumnach
macierzy A za pomocą funkcji
apply
,sum
orazprod
. - Obliczyć sumę wszystkich liczb z dwóch pierwszych wierszy macierzy A, a następnie sumę wszystkich liczb z pierwszej i trzeciej kolumny
- Co zwracają polecenia
t(A)
,det(A)
idiag(A)
? Wyznaczyć ślad macierzy A. - Co zwracają polecenia
A^2
,A*A
,A%*%A
? - Co zwracają polecenia
1/A
,A^(-1)
,solve(A)
? - Rozwiązać układ równań
\(\left\{ \begin{array}{ccc} 2x+23y+8z&=&5\\ 10x+6y+90z&=&6\\ 4x+7y+12z&=&7 \end{array} \right.\) - Wybrać te wiersze macierzy A, w których suma
elementów jest większa niż 30.
2 Ramki danych
Ramki danych (data.frame) są tablicami, których kolumny mogą być niejednorodne. Przykładowo, ramka może zawierać zarówno kolumny znakowe jak i numeryczne, ale każda kolumna zawiera elementy tego samego rodzaju. Jest to najważniejsza klasa obiektów dedykowana specjalnie do przechowywania danych.
Przykładowo, w ramce danych możemy umieścić zmienne jakościowe opisywane za pomocą znaków (np. kolumnę opisującą płeć M/K osoby lub jej status społeczno-zawodowy) oraz zmienne ilościowe opisywane za pomocą liczb (np. wzrost lub wiek). Wiele narzędzi statystycznych dostępnych w R jest dedykowanych tej klasie obiektów. Ramki danych tworzone są też zazwyczaj przez R podczas importu danych.
Ramki danych mogą być utworzone poprzez zgrupowanie wektorów
var1
, var2
,… o tej samej długości
poleceniem
data.frame(nazwa1=var1, nazwa2=var2,…)
Możliwe jest też przekształcenie macierzy w ramkę danych za pomocą
polecenia as.data.frame
.
2.1 Tworzenie ramek danych i podstawowe operacje na ramkach
v1=sample(1:12,30,rep=T) |
#Losuje ze zbioru {1…12} ciąg 30 liczb z powtórzeniami |
v2=sample(LETTERS[1:10],30,rep=T) |
#Losuje ze zbioru liter {A,B,…J} ciąg 30 liter z powtórzeniami |
v3=runif(30) |
#30 niezależnych realizacji rozkładu jednostajnego na przedziale [0,1] |
hist(v3) |
#Rysuje histogram zmiennej v3 |
v4=rnorm(30) |
#30 niezależnych realizacji rozkładu normalnego o średniej 0 i wariancji 1 |
hist(v4) |
#Rysuje histogram zmiennej v4 |
xx=data.frame(Age=v1,Firstname=v2,Height=v3,Weight=v4) |
#Tworzy ramkę danych z 4 zmiennymi i 30 osobnikami/obserwacjami |
str(xx) |
#Wyświetla strukturę obiektu |
xx$Firstname |
#Do zmiennych możemy się odnosić poprzez $ i nazwę |
xx[,1] |
#Do zmiennych możemy się odnieść przez [ ] , tak jak w
przypadku macierzy |
xx$Firstname[3] |
#Dostęp do trzeciego elementu wektora xx$Firstname |
xx[3,2] |
#To samo co wyżej |
summary(xx) |
#Podstawowe statystyki dla zmiennych |
str(xx) |
#Struktura obiektu może się różnić w zależności od występujących zmiennych ilościowych i jakościowych |
ma=matrix(1:15,nrow=3); ma |
#Tworzy nową macierz |
ma=as.data.frame(ma) |
#Zmienia macierz na ramkę danych |
ma |
#Wyświetlenie ramki |
str(ma) |
#Struktura ramki |
names(ma)=c('VA','VB','VC','VD','VE') |
#Przypisanie nazw zmiennym (kolumny ramki) |
row.names(ma)=c('l1','l2','l3') |
#Przypisanie nazw obserwacjom (wiersze ramki) |
ma |
#Wyświetlenie ramki |
2.2 Działania na zmiennych jakościowych (i ilościowych)
sex=sample(c('M','F'),100,rep=T) |
Wygenerowanie 100 realizacji zmiennej “sex” o wartościach “M” i “F” (mężczyzna, kobieta) |
height=rnorm(100,mean=170,sd=10) |
Wygenerowanie 100 realizacji zmiennej “height” z rozkładu normalnego o średniej “mean=170” i odchyleniu standardowym “sd=10” |
height[which(sex=='M')]=height[which(sex=='M')]+10 |
Dodanie do zmiennej “height” wartości 10, o ile zmiennej “sex” odpowiada wartość “M” - inaczej, mężczyźni statystycznie są wyżsi |
tapply(height,sex,mean) |
Obliczenie średniej zmiennej “height” osobno dla “M” i “F” |
tapply(height,sex,sd) |
Obliczenie odchylenia standardowego zmiennej “height” osobno dla “M” i “F” |
2.3 Gotowe zestawy danych
W R istnieją pewne gotowe zestawy danych, które można wykorzystać do ćwiczeń
data() |
Otwiera okno tekstowe z listą wszystkich tabel danych dostępnych w R |
women |
Wyświetla tabelę z danymi “women” |
? women |
Wyświetla opis ramki danych “women”. Dowiemy się, że wzrost jest w calach, a waga w funtach. |
names(women) |
Nazwy zmiennych w “women” |
attributes(women) |
Pewna charakterystyka “women”, w tym nazwy zmiennych, typ danych i nazwy obserwacji |
women$height |
Wyświetla wartości zmiennej “height” dla ramki
women |
apply(women,1,sum) |
Funkcję “apply” można stosować do ramek danych |
apply(women,2,max) |
Funkcję “apply” można stosować do ramek danych |
2.4 Zadania - Ramki danych
2.4.1 Zadanie
W ćwiczeniu wykorzystamy zbiór danych “iris” dostępny w R
Sprawdzić, czy jest to obiekt typu data.frame (ramka danych)
Co znajduje się w zbiorze danych?
Wpisz polecenie
summary(iris)
. Ile osobników gatunku versicolor znajduje się w tej bazie danych? Jaka jest średnia zmiennej Sepal.Width? Jaka jest najmniejsza wartość?Utwórz ramkę danych o nazwie “iris2”, który zawiera tylko osobniki gatunku “setosa”.
Posortuj osobniki gatunku “setosa” według długości działki kielicha (eng. sepal)
Znajdź średnie zmiennych Sepal.Length, Sepal.Width, Petal.Lehgth oraz Petal.Width przy użyciu funkcji
apply
orazmean
.Znajdź średnie zmiennej Sepal.Length dla każdego z trzech gatunków używając funkcji
tapply
orazmean
.
2.4.2 Zadanie
Poniższa tabela przedstawia liczbę studentów przyjętych w pięciu miastach z podziałem na 5 typów kierunków: nauki humanistyczne, ścisłe, medyczne, sportowe i techniczne w 2006 roku:
n. human. | n. ścisłe | medyczne | sportowe | techniczne | |
---|---|---|---|---|---|
Bordeaux | 12220 | 6596 | 7223 | 357 | 2239 |
Lyon | 15310 | 6999 | 10921 | 395 | 3111 |
Paryż | 112958 | 40244 | 46146 | 1247 | 7629 |
Rennes | 8960 | 6170 | 4661 | 279 | 4013 |
Tuluza | 12125 | 8233 | 6653 | 553 | 3178 |
Stworzyć ramkę danych zawierających dane z powyższej tabeli. W szczególności należy uzupełnić nazwy kolumn i wierszy jak wyżej (polecenia
names
irow.names
)Obliczyć całkowita liczbę studentów w danym mieście, a następnie uporządkować tabelę w porządku rosnącym względem tej liczby
Obliczyć całkowita liczbę studentów danego typu kierunków, a następnie uporządkować tabelę w porządku rosnącym względem tej liczby
Utworzyć nowa ramkę danych zawierającą tylko te miasta, gdzie liczba przyjętych na kierunki ścisłe jest wyższa niż liczba przyjęć na kierunki medyczne (jedno polecenie/jedna linijka)
2.5 Zadanie - metoda D’Hondta podziału mandatów w systemach wyborczych
2.5.1 Wstęp
Weźmiemy pod uwage wyniki wyborów do Sejmu RP z 15 października 2023, dane dla okręgu nr 13 (Kraków i okolice) dostępne na stronie
W tym okręgu do obsadzenia jest 14 mandatów, próg wyborczy 5% przekroczyło 5 komitetów wyborczych i tylko te komitety bierzemy pod uwagę:
partie=c("KO","PiS", "3Droga","Lewica", "Konfederacja")
glosy =c(232799,232430,127693,83633,58435)
l_mandatow=14
Gdyby zastosować wprost proporcjonalność zdobytych mandatów do liczby otrzymanych głosów dostalibyśmy wyniki ułamkowe:
#proporcjonalny podział głosów prowadzi do ułamkowych mandatów
razemglosy=sum(glosy)
udzial=glosy/razemglosy
ulamkowe_mandaty=l_mandatow*udzial
ulamkowe_mandaty
## [1] 4.434327 4.427298 2.432281 1.593031 1.113063
i taki wynik byłby trudny do zinterpretowania.
2.5.2 Metoda D’Hondta
Metoda ta jest algorytmem umożliwiającym niejako rozparcelowanie ułamkowych mandatów między komitety wyborcze. Opis algorytmu można znaleźć na
W skrócie algorytm polega na zbudowaniu tabelki jak niżej, gdzie w pierwszym wierszu umieszczamy liczby głosów uzyskane przez poszczególne komitety, a następne wiersze powstają przez podzielenie (zawsze) pierwszego wiersza przez kolejne liczby naturalne. Ilość wierszy takiej tabelki odpowiada liczbie mandatów do rozdzielenia (istnieje możliwość, że ktoś zgarnie wszystkie mandaty).
Następnie z tabelki wybieramy najwyższe wyniki aż do wyczerpania liczby mandatów do obsadzenia w okręgu.
2.5.3 Zadanie właściwe - część pierwsza
Zbudować ramkę danych - tabelkę wyników z ilorazami wynikającymi z metody d’Hondta. Efekt powinien przypominać
## KO PiS 3Droga Lewica Konfederacja
## 1 232799.00 232430.00 127693.000 83633.000 58435.000
## 2 116399.50 116215.00 63846.500 41816.500 29217.500
## 3 77599.67 77476.67 42564.333 27877.667 19478.333
## 4 58199.75 58107.50 31923.250 20908.250 14608.750
## 5 46559.80 46486.00 25538.600 16726.600 11687.000
## 6 38799.83 38738.33 21282.167 13938.833 9739.167
## 7 33257.00 33204.29 18241.857 11947.571 8347.857
## 8 29099.88 29053.75 15961.625 10454.125 7304.375
## 9 25866.56 25825.56 14188.111 9292.556 6492.778
## 10 23279.90 23243.00 12769.300 8363.300 5843.500
## 11 21163.55 21130.00 11608.455 7603.000 5312.273
## 12 19399.92 19369.17 10641.083 6969.417 4869.583
## 13 17907.62 17879.23 9822.538 6433.308 4495.000
## 14 16628.50 16602.14 9120.929 5973.786 4173.929
W powyższej ramce nazwy kolumn to komitety wyborcze, a nazwy wierszy to kolejne dzielniki.
Wskazówki:
liczba mandatów/wektor dzielników daje wektor ilorazów
wektory można połączyć w macierz za pomocą
cbind
przydatne:
as.data.frame
,colnames
,rownames
Z powyższej ramki danych należałoby wybrać 14 największych liczb (14, bo taka jest liczba mandatów w okręgu 13). Niestety, sortowanie macierzy jest nieco mało wygodne, w celu zautomatyzowania obliczeń zbudujemy inną, “lepszą” ramkę danych:
2.5.4 Zadanie właściwe - część druga
Ponieważ łatwiej posortować wektor, zbudujemy ramkę danych postaci:
## partia ilorazy
## 1 KO 232799.00
## 2 KO 116399.50
## 3 KO 77599.67
## 4 KO 58199.75
## 5 KO 46559.80
## 6 KO 38799.83
## partia ilorazy
## 65 Konfederacja 6492.778
## 66 Konfederacja 5843.500
## 67 Konfederacja 5312.273
## 68 Konfederacja 4869.583
## 69 Konfederacja 4495.000
## 70 Konfederacja 4173.929
gdzie pierwsza kolumna to kolejno sklonowane nazwy komitetów wyborczych (w liczbie równej liczbie mandatów), a druga kolumna to kolejne zestawy ilorazów.
Wskazówka: Ramkę tego typu możemy zbudować od
podstaw albo korzystając z ramki z pierwszej części i funkcji
stack()
.
Mając ramkę jak powyżej należy:
posortować malejąco kolumnę ilorazów (
order()
, czy możesort()
będzie lepszy?)wybrać pierwsze 14 wyników (odpowiadających liczbie mandatów)
wybrać nazwy komitetów odpowiadających 14 najlepszym wynikom/ilorazom
zliczyć liczbę mandatów za pomocą
table()
Powinniśmy dostać coś podobnego jak niżej, gdzie wyniki
table()
zostały jeszcze raz posortowane
##
## KO PiS 3Droga Konfederacja Lewica
## 5 5 2 1 1
## [1] 4.434327 4.427298 2.432281 1.593031 1.113063
Mamy też porównanie z ułamkowymi mandatami, widzimy gdzie te ułamkowe części się poprzesuwały.
Można też sprawdzić, czy wyliczony przez nas podział zgadza się z oficjalnymi wynikami
2.5.5 Zadanie właściwe - część trzecia
Powtórzyć podział mandatów dla innego, wybranego okręgu i porównać z oficjalnymi wynikami.
2.5.6 Zadanie dodatkowe 1
Sprawdzić, jak wyglądałby podział mandatów, gdyby komitety zawarły koalicje, np. jakbyśmy zsumowali głosy KO+Lewica+3droga i PiS+Konfederacja.
2.5.7 Zadanie dodatkowe 2 - metoda Sainte-Laguë
Innym sposobem podziału mandatów jest wykorzystanie metody Sainte-Laguë. Różnica w stosunku do metody D’Hondta polega na tym, że dzielniki to kolejne liczby nieparzyste.
Więcej informacji na Wikipedia metoda Sainte-Laguë
Zadanie:
zmodyfikować kod tak, aby obliczał liczbę mandatów metodą Sainte-Laguë
porównać otrzymane wyniki z metody Sainte-Laguë oraz metody D’Hondta
Możliwe jest, że w niektórych okręgach liczby mandatów otrzymanych za pomocą obu metod będą różne (metoda D’Hondta bardziej sprzyja większym partiom)
2.5.8 Ciekawostka
W polskim systemie wyborczym, gdy znamy już liczbę mandatów przypadającą danemu komitetowi, bierzemy pod uwagę indywidualne wyniki kandydatów z danej listy.
Stąd też “układanki wyborcze”, tak aby znane nazwisko zdobyło nie tylko mandat dla siebie, ale znacznie poprawiło ogólny wynik listy, co daje większą liczbę mandatów.
3 Listy
Lista jest uporządkowanym zbiorem obiektów, nie koniecznie tego
samego typu. Elementami list mogą być dowolne obiekty zdefiniowane w R.
Można utworzyć na przykład listę, która zawiera wektor liczbowy i
macierz znaków. Własność ta jest wykorzystywana w szczególności przez
niektóre funkcje do zwracania złożonych wyników w formie pojedynczego
obiektu. Listę tworzy się za pomocą funkcji
list(nazwa1=el1, nazwa2=el2,…)
. Do każdego elementu listy
można przejść używając jego indeksu w nawiasach podwójnych
[[…]]
lub jego nazwy poprzedzonej znakiem
$
.
li=list(num=1:5,y="color",a=TRUE) |
utworzenie listy z 3 obiektami |
li |
wyświetlenie listy |
li$num |
dostęp do elementu listy przez $ |
li$a |
dostęp do elementu listy przez $ |
li[[1]] |
dostęp do elementu listy przez [[…]] |
li[[3]] |
dostęp do elementu listy przez [[…]] |
a=matrix(c(6,2,0,2,6,0,0,0,36),nrow=3) |
utworzenie macierzy |
eigen(a) |
obliczenie rozkładu Jordana macierzy |
res=eigen(a) |
Wynik podawany jest w postaci listy |
attributes(res) |
Pozwala na wyświetlenie nazw elementów listy |
str(res) |
Wyświetla strukturę listy |
res$values |
Wyświetlenie wartości własnych |
res$vectors |
Wyświetlenie wektorów własnych |
res$vectors[,1] |
Wyświetlenie pierwszego wektora własnego |
diag(res$values) |
Macierz Jordana (dokładniej macierz diagonalna, której elementy ma przekątnej pochodzą z wektora zawierającego wartości własne) |
res$vectors%*%diag(res$values)%*%t(res$vectors) |
Rozkład Jordana, macierz odwrotna = transponowana |
x<-list(a=1:10,beta=exp(-3:3),logic=c(TRUE,FALSE,FALSE,TRUE)) |
utworzenie nowej listy |
lapply(x,mean) |
Polecenie lapply stosuje zadaną funkcję (tutaj
mean ) do każdego elementu listy |
3.1 Zadania - Listy
3.1.1 Zadanie
Utworzyć 3-elementową listę zawierającą Twoje nazwisko, imiona rodziców oraz miejsce urodzenia (fikcyjne, RODO itd). Nazwy elementów listy to “nazwisko”, “imiona_rodzicow” i “miejsce_urodzenia”.
3.1.2 Zadanie
Utworzyć (ponownie) macierz
\(\mathbf{A}=\left( \begin{array}{ccc} 2&23&8\\10&6&90\\4&7&12\end{array}\right)\)
za pomocą poleceńcbind
i/lubmatrix
.Obliczyć wartości własne i wektory własne macierzy. Czy macierz jest diagonalizowalna?
Na podstawie poprzedniego pytania obliczyć \(\mathbf{A}^n\) dla \(n=10\) oraz \(n=50\) nie używając pętli (algebra liniowa…). Może się przydać polecenie
inv
z pakietumatlib
. Ładowanie za pomocąlibrary(matlib)