Menu

Macierze w R: matrix(), cbind, rbind i działania na macierzach

Jak budować macierze przez matrix(), cbind() i rbind(), indeksować wiersze i kolumny oraz odróżniać mnożenie element po elemencie * od prawdziwego mnożenia macierzy %*%.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

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 * a działa element po elemencie: każda komórka jest mnożona przez odpowiadającą jej komórkę. 1 2 3 4 stają się 1 4 9 16 w tym samym kształcie. To zwykła arytmetyka wektorowa, ten sam *, którego używasz na wektorach.
  • a %*% a to 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żesz byrow = TRUE.
  • Indeksuj jako m[row, col]; pusta pozycja oznacza "wszystkie"; dodawaj drop = FALSE, gdy wycinasz pojedyncze wiersze albo kolumny w kodzie.
  • cbind() i rbind() 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.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ