R에는 다른 많은 언어와 똑같은 연산자들이 있어요:
1 == 2 # FALSE
1 != 2 # TRUE
1 < 2 # TRUE
1 > 2 # FALSE
1 <= 2 # TRUE
1 >= 2 # FALSE
if-then-else의 기본 형태는 이래요:
if (x > 10) {
y <- "big"
} else if (x > 2) {
y <- "medium"
} else {
y <- "tiny"
}
이때 불리언을 감싸는 괄호 ( )와 본문을 감싸는 중괄호 { }가 모두 필요해요.
단순한 if문은 짧게 줄일 수 있어요:
if (x == 0) return("success")
앞으로 배울 vector-filtering 개념을 미리 살펴보면, 괄호 () 안의 조건절은 하나의 TRUE/FALSE로 평가되어야 해요.
비교에 벡터를 넣으면 보통 불리언 벡터가 나오기 때문에, 이런 값은 all()(모든 값이 TRUE인가요?)이나 any()(값이 하나라도 TRUE인가요?) 같은 집계 함수로 감싸야 해요.
numbers <- c(4,5,7,9,10,11)
numbers %% 3 == 0 # gives vector of booleans
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE
# use any() to get a single TRUE/FALSE
if (any(numbers %% 3 == 0)) print("1 or more numbers are divisible by 3")
#> [1] "1 or more numbers are divisible by 3"
ifelse 함수결과가 참/거짓 두 가지뿐이라면, 다른 형태의 if-else가 유용할 수 있어요.
y <- ifelse(x > 8, "big", "small")
# Don't mix result types:
z <- ifelse(x > 100, 100, "small") # numeric or string result? Expect problems!
ifelse()는 정확히 세 개의 매개변수를 받아요:
TRUE일 때의 값FALSE일 때의 값.벡터를 입력으로 넣어도 되고, 그러면 벡터가 출력으로 나와요.
이때 두 분기의 결과가 같은 데이터 타입이 되도록 해요. 숫자형, 문자형, 논리형 등이에요.
이 내용은 vector-functions 개념에서 다뤄요.
두 결과 값(위 예시의 "big", "small")은 각각 하나의 값이어야 해요.
아쉽게도 여기에 더 긴 벡터를 넣으면 R이 경고 메시지 하나 없이 예상 밖의 혼란스러운 동작을 할 가능성이 커요.
if_else 함수R 언어 관리자들은 가능한 한 호환성을 깨뜨리는 변경을 피하는 방침을 지켜요. 덕분에 CRAN에 있는 수많은 서드파티 패키지를 안정적으로 유지할 수 있지만, 기본 R을 현대적인 프로그래밍 개념으로 업데이트할 여지는 줄어들어요.
최근 몇 년 사이에는 원래 R 설계의 장단점을 수십 년간 경험한 바탕 위에서, R의 기능을 확장하거나 때로는 대체하는 패키지들이 여럿 나왔어요.
이 패키지들이 tidyverse 컬렉션을 이루고 있어요.
이 패키지들은 2023년에 Exercism 테스트 러너에 추가되었고, 연습 문제에서 자유롭게 사용할 수 있어요.
우리 R 트랙은 tidyverse가 추가되기 몇 년 전에 만들어졌기 때문에, 많은 커뮤니티 풀이가 기본 언어만 고수하는 것을 보게 될 거예요.
dplyr 패키지dplyr는 주로 데이터프레임을 다루는 패키지예요(강의 후반부에서 다뤄요).
코드 맨 위에 library(dplyr)를 쓰거나, 컬렉션 전체를 불러오려면 library(tidyverse)를 쓰면 돼요.
이름이 가려졌다는 경고 메시지가 보일 수도 있지만, 이건 거의 문제가 되지 않아요.
지금 다루는 개념에서는 if_else 함수를 짚고 넘어갈 만해요.
기본 R의 ifelse와 거의 비슷해요.
library(dplyr) # warnings not shown
x <- 10
if_else(x > 8, "big", "small")
#> [1] "big"
가장 큰 차이는 if_else가 선택적인 네 번째 인자를 받을 수 있다는 점이에요. R에서 결측값을 나타내는 NA를 위한 자리예요.
xs <- c(3, NA, 10, NA, 4) # a 5-element vector
xs
#> [1] 3 NA 10 NA 4
if_else(xs > 8, "big", "small", "missing")
#> [1] "small" "missing" "big" "missing" "small"
# contrast:
ifelse(xs > 8, "big", "small")
#> [1] "small" NA "big" NA "small"
if_else가 예전 ifelse보다 오류 메시지를 훨씬 잘 보여 준다는 것도 알게 될 거예요.
dplyr 패키지를 불러오면 between() 함수도 쓸 수 있어요.
R은 비교를 연달아 쓰는 것을 허용하지 않아서, 1 <= x <= 5라고 쓰면 오류 메시지가 나와요.
dplyr을 불러온 상태라면 between(x, 1, 5)는 x >= 1 & x <= 5와 같고, 아마 더 읽기 쉬울 거예요.
하한과 상한을 모두 포함해요.