Menu

Wektory w R: c(), seq(), indeksowanie i obliczenia wektorowe

Wektory to podstawowa jednostka R, nawet pojedyncza liczba jest wektorem. Jak tworzyć je przez c(), indeksować (od 1!), filtrować maskami logicznymi i liczyć na całych wektorach naraz.

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

W R wszystko jest wektorem

Większość języków ma skalary, czyli pojedyncze wartości, a do tego jakiś typ kontenera na kilka z nich. R pomija skalar. Wektor to uporządkowany zbiór wartości jednego typu i to na nim zbudowane jest wszystko inne. Nawet coś, co wygląda na samotną liczbę, jest wektorem o długości 1:

c(), skrót od combine (połącz), pozwala zbudować wektor ręcznie. length() mówi, ile ma elementów. A samo 5 zwraca TRUE dla is.vector i ma długość 1: R nigdy nie przestaje pracować z wektorami, po prostu czasem są one bardzo krótkie.

Z tego projektu wynika, że kod R wygląda inaczej niż kod w Pythonie czy JavaScripcie: operacje, dla których gdzie indziej pisze się pętlę, działają na całych wektorach w jednym wyrażeniu. Dojdziemy do tego niżej.

Jedna zasada, którą warto przyswoić już teraz: wszystkie elementy wektora mają ten sam typ. Jeśli przekażesz c() mieszankę, nie będzie narzekać, tylko po cichu przekształci wszystko na najbardziej elastyczny obecny typ:

Napis w mieszance zamienia wszystko w napisy ("1", "TRUE"). Wartości logiczne wśród liczb stają się 1 i 0. Ta koercja (konwersja typów) działa według stałej hierarchii: logical → integer → double → character, i odbywa się bez ostrzeżenia. Dlatego zabłąkane "7" w kolumnie liczb może po cichu zamienić cały zbiór danych w tekst. Pełną hierarchię opisuje artykuł o typach danych; jeśli potrzebujesz przechowywać naprawdę mieszane wartości, do tego służą listy.

Generowanie ciągów: :, seq() i rep()

Wpisywanie każdego elementu do c() szybko się nudzi. R ma trzy skróty dla regularnych wzorców:

  • 1:10 to codzienny sposób: liczby całkowite od jednej granicy do drugiej, z krokiem 1.
  • seq() go uogólnia: wybierz krok przez by = albo podaj, ile elementów chcesz, przez length.out =, a R sam wyliczy odstępy.
  • seq_len(n) tworzy liczby od 1 do n i jest bezpiecznym sposobem budowania indeksów pętli: w przeciwieństwie do 1:n poprawnie daje pusty wektor, gdy n wynosi 0, zamiast liczyć wstecz 1 0.
  • rep() powtarza: times = powtarza cały wektor od początku do końca (1 2 1 2 1 2), a each = powtarza każdy element w miejscu (1 1 1 2 2 2). Łatwo je pomylić; uruchom fragment i porównaj.

Indeksowanie: R liczy od 1

Nawiasy kwadratowe wyciągają elementy. Pierwszy element to [1], a nie [0]. Jeśli przychodzisz z Pythona albo JavaScriptu, to najczęstsze wczesne potknięcie:

Trzy rzeczy, przy których warto się zatrzymać:

  • Możesz indeksować wektorem pozycji: fruits[c(2, 4)] pobiera za jednym razem drugi i czwarty element.
  • Ujemne indeksy oznaczają „wszystko oprócz”. fruits[-1] to wektor bez pierwszego elementu. To zupełnie coś innego niż w Pythonie, gdzie -1 oznacza ostatni element. W jednym wywołaniu nie można mieszać indeksów dodatnich i ujemnych.
  • fruits[0] nie jest błędem: zwraca pusty character(0). Błąd o jeden w R często daje ciche puste wyniki zamiast awarii, więc warto sprawdzić length(), gdy coś dalej w kodzie wygląda na tajemniczo puste.

Elementy mogą też mieć nazwy, co daje trzeci sposób indeksowania, według etykiety:

Nazwane wektory działają jak lekka tablica wyszukiwania i sprawiają, że kod jest czytelny: prices["tea"] mówi, o co chodzi, a prices[2] nie.

Maski logiczne i which()

Najpotężniejszy sposób indeksowania to wektor logiczny, czyli maska wartości TRUE/FALSE o tej samej długości co dane. Dokładnie to daje każde porównanie na wektorze:

temps > 24 nie daje jednej odpowiedzi, tylko pięć, po jednej na element. Wstawienie tej maski do [ ] zostawia elementy, dla których maska ma wartość TRUE. Warunki łączysz przez & (i) oraz | (lub), które opisuje artykuł o operatorach.

which() tłumaczy maskę na pozycje: tutaj 2 3 5, czyli indeksy gorących odczytów. Sięgaj po nią, gdy musisz wiedzieć, gdzie są dopasowania: żeby je zgłosić albo zaindeksować inny wektor w tych samych miejscach. Do zwykłego filtrowania temps[temps > 24] jest bardziej bezpośrednie niż temps[which(temps > 24)].

Ten wzorzec filtrowania maską to kręgosłup praktycznie całej pracy z danymi w R. Wraca od razu, gdy filtrujesz wiersze ramki danych.

Obliczenia wektorowe i zasada recyklingu

Arytmetyka w R działa element po elemencie na całych wektorach, bez pętli:

Pierwsza linia to główna cecha: prices * 2 podwaja każdy element. Tam, gdzie inne języki potrzebują pętli for, R potrzebuje operatora, a forma wektorowa jest zarówno krótsza, jak i szybsza, bo pętla odbywa się pod spodem w zoptymalizowanym C. Pisz pętlę for, gdy każdy krok zależy od poprzedniego; do obliczeń element po elemencie używaj wektoryzacji.

Trzecia linia pokazuje zasadę recyklingu: gdy wektory mają różne długości, R powtarza krótszy, żeby pasował. c(10, 20) zostaje powtórzony do 10 20 10 20, co daje 11 22 13 24. Powtarzanie 2 na wektorze o długości 3 to dokładnie to, dzięki czemu zadziałało prices * 2: skalar to po prostu wektor o długości 1, który jest powtarzany.

Recykling działa czysto, gdy dłuższa długość jest dokładną wielokrotnością krótszej. Gdy nie jest, R i tak oblicza wynik i zgłasza ostrzeżenie:

Dostajesz 11 22 13 i ostrzeżenie, że długość dłuższego obiektu nie jest wielokrotnością długości krótszego. Traktuj to ostrzeżenie jak zgłoszenie błędu: częściowy recykling prawie nigdy nie jest tym, o co ci chodziło, i zwykle oznacza, że dwa wektory, które miały mieć tę samą długość, jej nie mają.

Sortowanie, odwracanie, usuwanie duplikatów

Trzy małe narzędzia, których będziesz używać cały czas:

sort() porządkuje wartości, rev() odwraca istniejącą kolejność bez sortowania, a unique() usuwa duplikaty, zachowując pierwsze wystąpienia. Żadna z nich nie modyfikuje x: jak prawie wszystko w R zwracają nowy wektor, a oryginał zostawiają w spokoju.

Najważniejsze informacje

  • Wektor to podstawowa jednostka R: uporządkowany, jednego typu, a nawet pojedyncze wartości są wektorami o długości 1.
  • Buduj przez c(), generuj wzorce przez :, seq() i rep() i pamiętaj, że c() po cichu przekształca mieszane typy.
  • Indeksowanie zaczyna się od 1; ujemne indeksy usuwają elementy; nazwy pozwalają indeksować według etykiety.
  • Maski logiczne (x[x > 5]) to idiom filtrowania w całym języku; which() zamienia maskę na pozycje.
  • Obliczenia są wektorowe, krótsze wektory są powtarzane, a ostrzeżenie o częściowym recyklingu oznacza, że masz błąd.

Dalej: listy, czyli kontener na wartości, które nie mają jednego wspólnego typu.

Najczęściej zadawane pytania

Jak utworzyć wektor w R?

Funkcją c() (skrót od combine, czyli połącz): x <- c(10, 20, 30). Dla regularnych ciągów użyj 1:10, seq(0, 1, by = 0.25) albo rep(0, 5). Każdy element musi ostatecznie mieć ten sam typ: jeśli mieszasz typy, R po cichu przekształca wszystkie na najbardziej elastyczny z nich.

Czy indeksowanie w R zaczyna się od 0 czy od 1?

Od 1. x[1] to pierwszy element, x[length(x)] ostatni. To zaskakuje każdego, kto przychodzi z Pythona, JavaScriptu albo C: nie ma elementu x[0] (zapytanie o niego zwraca pusty wektor, a nie błąd, więc taki bug jest cichy).

Co robi zasada recyklingu w R?

Gdy wykonujesz działania na dwóch wektorach różnej długości, R powtarza krótszy, aż dorówna dłuższemu. c(1, 2, 3, 4) + c(10, 20) daje 11 22 13 24. Jeśli dłuższa długość nie jest wielokrotnością krótszej, R i tak oblicza wynik, ale zgłasza ostrzeżenie. Traktuj to ostrzeżenie jak błąd.

Co robi which() w R?

Zamienia wektor logiczny na pozycje jego wartości TRUE. Jeśli x > 5 daje FALSE TRUE TRUE, to which(x > 5) daje 2 3. Używaj jej, gdy potrzebujesz samych pozycji; do zwykłego filtrowania prostsze jest indeksowanie bezpośrednio wektorem logicznym (x[x > 5]).

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ