Macierz to wektor z wymiarami
Macierz w R to prostokąt wartości, czyli wiersze i kolumny, w którym każda komórka ma ten sam typ, zwykle liczbowy. Pod spodem to dosłownie wektor z doczepionym atrybutem dim, co wyjaśnia większość jej zachowania: jeden typ w całości i wektorowa matematyka wszędzie.
Tworzysz ją, przekształcając wektor przez matrix():
Sześć wartości, dwa wiersze: R sam wylicza, że potrzebne są trzy kolumny. dim() zwraca oba wymiary naraz jako 2 3, a nrow() i ncol() podają je osobno.
Przyjrzyj się wypisanej macierzy: wartości 1 2 idą w dół pierwszej kolumny, potem 3 4 w dół kolejnej. R domyślnie wypełnia macierze kolumna po kolumnie. Jeśli twoje dane czyta się wiersz po wierszu (a tak zwykle zapisują je ludzie), powiedz to przez byrow = TRUE:
Teraz pierwszy wiersz to 1 2 3. Zapomniane byrow = TRUE nie powoduje błędu: po cichu daje układ tych samych liczb wyglądający jak transpozycja. Dlatego niech sprawdzanie wypisanego układu stanie się nawykiem za każdym razem, gdy tworzysz macierz z surowych wartości.
Indeksowanie: m[row, column]
Indeksowanie macierzy przyjmuje dwie pozycje w jednej parze nawiasów: wiersz przed przecinkiem, kolumnę po nim, obie liczone od 1:
Pusta pozycja oznacza "wszystkie": m[1, ] to cały pierwszy wiersz, m[, 2] cała druga kolumna. Zauważ, że oba wracają jako zwykłe wektory, bo R usuwa wymiar, który skurczył się do rozmiaru 1. Interaktywnie to wygodne, w kodzie to pułapka, bo funkcja oczekująca macierzy zakrztusi się wektorem. Poproś R o zachowanie kształtu przez drop = FALSE:
dim() zwraca teraz 1 3, więc to nadal macierz. Za każdym razem, gdy wycinasz pojedynczy wiersz albo kolumnę wewnątrz funkcji, pisz drop = FALSE. Błąd, któremu to zapobiega (kod działający na szerokich danych i psujący się na danych z jedną kolumną), jest wyjątkowo przykry do wytropienia.
Maski logiczne też tu działają: m[m > 3] zwraca wszystkie komórki większe niż 3 jako wektor.
Budowanie przez cbind() i rbind()
Zamiast przekształcać jeden długi wektor, możesz złożyć macierz z kawałków: cbind() łączy wektory jako kolumny, a rbind() jako wiersze. Te same funkcje rozszerzają też istniejącą macierz:
Nazwy podróżują razem z wektorami: cbind() automatycznie użyło heights i weights jako nazw kolumn, dzięki czemu wypisana macierz jest czytelna. Obie funkcje wymagają zgodnych długości (z recyklingiem dla wartości o długości 1); dołączenie wektora długości 3 do macierzy z 4 wierszami skończy się ostrzeżeniem.
Nazwy kolumn i wierszy można też ustawić bezpośrednio przez colnames(m) <- ... i rownames(m) <- ..., a potem indeksować po nazwie: people[, "weights"].
Mnożenie element po elemencie * kontra prawdziwe mnożenie macierzy %*%
Oto rozróżnienie, które w całym tym artykule ma największe znaczenie. R ma dwa operatory mnożenia macierzy i liczą one zupełnie różne rzeczy:
a * adziała element po elemencie: każda komórka jest mnożona przez odpowiadającą jej komórkę.1 2 3 4stają się1 4 9 16w tym samym kształcie. To zwykła arytmetyka wektorowa, ten sam*, którego używasz na wektorach.a %*% ato mnożenie macierzy z algebry liniowej: każda komórka wyniku to wiersz pierwszej macierzy razy kolumna drugiej, zsumowane. Te same dane wejściowe dają7 10 15 22, czyli zupełnie inne liczby.
Uruchom fragment i porównaj oba wyniki obok siebie. Zobaczenie, że różnią się przy identycznych danych, sprawia, że to rozróżnienie zostaje w pamięci. Jeśli napiszesz * tam, gdzie matematyka wymaga %*%, R cię nie ostrzeże (przy macierzach kwadratowych kształty pasują w obu przypadkach), po prostu dostaniesz złe liczby. W kodzie statystycznym (macierze kowariancji, algebra modeli liniowych) to jeden z klasycznych cichych błędów.
t() transponuje, czyli zamienia wiersze z kolumnami, i stale pojawia się obok %*%, bo mnożenie macierzy wymaga zgodności wewnętrznych wymiarów:
Dla kompletności: solve(m) odwraca macierz, a %*% z wektorem traktuje go jak macierz z jedną kolumną. Większość pracy z danymi nie wymaga schodzenia głębiej.
Podsumowania wierszy i kolumn
Sumowanie albo uśrednianie w wierszach i kolumnach jest tak częste, że R ma do tego osobne, szybkie funkcje:
rowSums() zwija każdy wiersz do jednej liczby (tutaj 6 15), colSums() każdą kolumnę (5 7 9), a warianty Means liczą średnią. Wybieraj je zamiast ręcznie pisanych pętli, a nawet zamiast apply(m, 1, sum), bo są czytelniejsze i szybsze. Do podsumowań, których te cztery nie obejmują (np. maksimum w każdej kolumnie), ogólnym narzędziem jest rodzina apply: apply(m, 2, max).
Macierz czy ramka danych?
Obie są prostokątne, więc po którą sięgnąć?
- Macierz: każda komórka tego samego typu i liczy się matematyka. Obliczenia numeryczne, algebra liniowa, obliczanie odległości, siatki podobne do obrazów. Macierze są lżejsze, a ich operacje szybsze właśnie dzięki gwarancji jednego typu.
- Ramka danych: kolumny różnych typów, czyli imiona obok wieku obok flag logicznych. To prawdziwe dane tabelaryczne i właśnie ich oczekuje prawie każda funkcja do analizy danych.
Dobra zasada: jeśli naturalnie otworzyłoby się to w arkuszu kalkulacyjnym z nazwanymi, mieszanymi kolumnami, to jest ramka danych. Jeśli to siatka liczb, na której chcesz wykonywać algebrę, to macierz. Konwersja w obie strony jest łatwa (as.matrix(), as.data.frame()), ale as.matrix() na ramce danych z jakąkolwiek kolumną tekstową zamienia wszystko na tekst, więc konwertuj tylko kolumny liczbowe.
Co warto zapamiętać
- Macierz to wektor z wymiarami: jeden typ w całości, budowana przez
matrix(data, nrow, ncol), wypełniana kolumna po kolumnie, chyba że przekażeszbyrow = TRUE. - Indeksuj jako
m[row, col]; pusta pozycja oznacza "wszystkie"; dodawajdrop = FALSE, gdy wycinasz pojedyncze wiersze albo kolumny w kodzie. cbind()irbind()składają macierze z wektorów albo rozszerzają istniejące.*działa element po elemencie,%*%to prawdziwe mnożenie macierzy: te same dane, różne odpowiedzi, żadnego ostrzeżenia.rowSums()/colSums()/rowMeans()/colMeans()obsługują codzienne podsumowania.
Dalej: czynniki (factors), czyli jak R przechowuje dane kategoryczne i jakie pułapki się z tym wiążą.
Najczęściej zadawane pytania
Jak utworzyć macierz w R?
matrix(1:6, nrow = 2) przekształca wektor w 2 wiersze i 3 kolumny, wypełniając kolumna po kolumnie. Dodaj byrow = TRUE, żeby wypełniać wiersz po wierszu. Macierz można też złożyć z wektorów: cbind() skleja je jako kolumny, a rbind() jako wiersze.
Czym różni się * od %*% w R?
* mnoży element po elemencie: każda komórka razy odpowiadająca jej komórka, a kształty muszą do siebie pasować. %*% to prawdziwe mnożenie macierzy z algebry liniowej (wiersze razy kolumny, więc wewnętrzne wymiary muszą się zgadzać). Na tych samych macierzach dają zupełnie różne wyniki, a użycie * zamiast %*% to klasyczny cichy błąd.
Jak pobrać jeden wiersz albo kolumnę macierzy w R?
Zostaw drugą pozycję pustą: m[1, ] to pierwszy wiersz, m[, 2] to druga kolumna. Domyślnie oba wracają jako zwykłe wektory. Dodaj drop = FALSE, jak w m[1, , drop = FALSE], żeby zachować wynik jako macierz z jednym wierszem albo jedną kolumną. Ma to znaczenie, gdy dalszy kod oczekuje dwóch wymiarów.