Menu

Operatory w R: arytmetyczne, porównania, logiczne, %in% i %%

Wszystkie operatory, których potrzebujesz w R: arytmetyka razem z %% i %/%, wektorowe porównania, różnica między & a && oraz %in% do sprawdzania przynależności.

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

Operatory, które daje R

Operatory w R dzielą się na cztery robocze grupy: arytmetyczne (+ - * / ^ %% %/%), porównania (== != < <= > >=), logiczne (& | && || ! xor) oraz test przynależności %in%. Dwie rzeczy odróżniają je od większości języków: prawie wszystkie są wektorowe, czyli działają naraz na całych wektorach, element po elemencie, a R ma dwa operatory AND i dwa operatory OR, których nie można stosować zamiennie. Ta strona omawia je wszystkie oraz pułapki kolejności działań, które po cichu dają złe odpowiedzi.

Arytmetyka: +, -, *, /, ^, %% i %/%

Pierwsze pięć robi to, czego się spodziewasz. Dwa otoczone znakami procentu, czyli %% (modulo, reszta) i %/% (dzielenie całkowite, iloraz), to te, których ludzie szukają:

Zauważ, że / zawsze wykonuje dzielenie zmiennoprzecinkowe: 17 / 5 to 3.4, nigdy 3. Jeśli chcesz część całkowitą, właśnie do tego służy %/%.

Codzienną pracą %% jest sprawdzanie podzielności. Liczba jest parzysta, gdy dzielenie przez 2 nie zostawia reszty:

Na drugiej linii warto się zatrzymać: przy ujemnym argumencie %% w R zwraca wynik ze znakiem dzielnika (-7 %% 3 to 2, bo -7 = -3 * 3 + 2). Niektóre języki robią to odwrotnie; jeśli przenosisz kod, sprawdź to.

Operatory porównania są wektorowe

==, !=, <, <=, >, >= porównują element po elemencie i zwracają wektor logiczny, a nie jedną odpowiedź:

To silnik niemal całego filtrowania w R: porównujesz cały wektor z wartością, dostajesz maskę logiczną i używasz jej do wybrania podzbioru. Jedna przestroga przy == na ułamkach: liczby zmiennoprzecinkowe są przechowywane w przybliżeniu, więc 0.1 + 0.2 == 0.3 daje FALSE. Do porównań ułamków dziesiętnych wybieraj all.equal() albo sprawdzaj abs(x - y) < 1e-9.

Operatory logiczne: & kontra && (klasyczne pomieszanie)

R ma dwa operatory AND i dwa operatory OR, a wybranie złego to obowiązkowy rytuał przejścia.

& i | są wektorowe. Łączą dwa wektory logiczne element po elemencie:

Używaj ich zawsze, gdy budujesz filtr na danych: df[df$age > 30 & df$city == "Lisbon", ].

&& i || są skalarne i stosują skrócone obliczanie. Przyjmują pojedyncze wartości, zwracają jedno TRUE/FALSE i całkowicie pomijają drugi argument, jeśli pierwszy już rozstrzyga odpowiedź:

Druga linia pokazuje skrócone obliczanie: ponieważ x < 0 to FALSE, R nigdy nie wykonuje wywołania stop(). Właśnie dlatego && pasuje do warunków if(): możesz napisać if (!is.na(x) && x > 10), a część x > 10 zostanie bezpiecznie pominięta, gdy x to NA.

Praktyczna zasada: &/| do wektorów i filtrowania danych, &&/|| do warunków if(). Od R 4.3 jest to egzekwowane na serio: przekazanie do && albo || wektora o długości większej niż 1 to błąd (starsze wersje R po cichu brały tylko pierwszy element, co przez lata ukrywało prawdziwe błędy).

xor(a, b) uzupełnia zestaw: daje TRUE, gdy dokładnie jeden z dwóch argumentów jest TRUE:

%in%: sprawdzanie przynależności

x %in% table pyta dla każdego elementu x: "czy występuje on gdziekolwiek w table?". To jeden z najczęściej używanych operatorów w prawdziwym kodzie R:

Sprawdzana strona może być całym wektorem, dzięki czemu %in% jest naturalnym narzędziem do filtrowania wierszy według zbioru dozwolonych wartości.

Jest też lepszy od alternatywy, którą trzeba by inaczej napisać, czyli łańcucha == sklejonego przez |:

Przy pięciu dozwolonych wartościach łańcuch == zamienia się w ścianę powtórzeń, a wersja z %in% po prostu wydłuża wektor. Jest też druga, subtelniejsza przewaga: %in% nigdy nie zwraca NA:

NA == 1 daje NA, bo R nie może wiedzieć, czy nieznana wartość równa się 1. To zachowanie szczegółowo opisuje artykuł o brakujących wartościach. Takie NA zatruwa potem każde if(), do którego trafi. %in% omija cały problem, bo zawsze odpowiada TRUE albo FALSE, i dlatego jest bezpieczniejszym wyborem w warunkach na danych, w których mogą być braki.

Pułapki kolejności działań

Dwie pułapki kolejności operatorów odpowiadają za nieproporcjonalnie dużą część chwil "R jest zepsuty". Po pierwsze, ^ wiąże mocniej niż jednoargumentowy minus:

Po drugie, dwukropek wiąże mocniej niż dwuargumentowa arytmetyka:

W razie wątpliwości dodaj nawiasy. Nic nie kosztują, a każdy czytelnik (łącznie z tobą w przyszłości) odczyta je tak samo jak interpreter.

$ i [ ]: operatory dostępu

Stale będziesz też widzieć $, [ ] i [[ ]]. Technicznie to również operatory, tylko służą do wyciągania wartości ze struktur, a nie do obliczeń:

Szczegółowo omawiają je strony o wektorach, listach i ramkach danych; tutaj wystarczy rozpoznawać je jako członków tej samej rodziny operatorów.

Co warto zapamiętać

  • %% daje resztę, %/% iloraz całkowity; x %% 2 == 0 sprawdza parzystość.
  • Porównania są wektorowe: zwracają wektor logiczny, którym możesz filtrować.
  • &/| łączą wektory element po elemencie; &&/|| służą do pojedynczych wartości w if() i stosują skrócone obliczanie. Od R 4.3 && na dłuższym wektorze to błąd.
  • x %in% table zastępuje łańcuchy == i nigdy nie zwraca NA.
  • -2^2 to -4, a 1:n - 1 zaczyna się od 0: w razie wątpliwości dodawaj nawiasy.

Dalej: wykorzystanie tych operatorów w if, else i ifelse(), czyli instrukcjach warunkowych w R.

Najczęściej zadawane pytania

Co robi %% w R?

%% to operator modulo: zwraca resztę z dzielenia. 17 %% 5 to 2. Jego towarzysz %/% wykonuje dzielenie całkowite i zwraca iloraz bez reszty: 17 %/% 5 to 3. Klasyczne zastosowanie %% to sprawdzanie parzystości: x %% 2 == 0.

Czym różni się & od && w R?

& jest wektorowy: porównuje dwa wektory element po elemencie i zwraca wektor tej samej długości. && działa tylko na pojedynczych wartościach, stosuje skrócone obliczanie (pomija drugi argument, jeśli pierwszy już przesądza o wyniku) i zwraca dokładnie jedno TRUE albo FALSE. Używaj & do filtrowania wektorów, a && w warunkach if(). Od R 4.3 przekazanie do && albo || wektora dłuższego niż 1 to błąd, a nie ostrzeżenie.

Co robi %in% w R?

x %in% table sprawdza, czy każdy element x występuje gdziekolwiek w table, i zwraca TRUE albo FALSE dla każdego elementu. "mango" %in% basket zastępuje łańcuch porównań == połączonych przez |, a w przeciwieństwie do == nigdy nie zwraca NA: brakująca wartość po stronie sprawdzanej po prostu daje FALSE.

Dlaczego -2^2 zwraca -4 w R?

Ponieważ ^ wiąże mocniej niż jednoargumentowy minus, R czyta -2^2 jako -(2^2), czyli -4. Jeśli chodzi ci o kwadrat minus dwóch, napisz (-2)^2, co daje 4. Dwukropek ma podobną pułapkę: 1:n - 1 oznacza (1:n) - 1, a nie 1:(n - 1).

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ