Menu

R의 if else: if, else if, ifelse(), switch()

R의 조건 논리입니다. if/else if/else 문법, 스크립트를 깨뜨리는 중괄호 함정, 벡터 전체에 쓰는 벡터화된 ifelse(), 그리고 다중 분기를 위한 switch()를 다룹니다.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

if 문

R의 if 문은 조건이 TRUE일 때만 코드 블록을 실행합니다. 조건은 괄호 안에, 코드는 중괄호 안에 두고, 선택적인 else가 그렇지 않을 때의 동작을 제공합니다.

조건 score >= 60은 하나의 TRUE로 평가되므로 첫 분기가 실행됩니다. 이런 조건을 만드는 재료가 바로 비교와 논리 연산자==, >=, &&, %in% 등입니다.

결과가 셋 이상이면 else if로 검사를 이어 붙입니다. R은 첫 조건부터 아래로 훑으며 조건이 TRUE 분기를 실행하고 나머지는 건너뜁니다.

순서가 중요합니다. 85 >= 8085 >= 70보다 먼저 검사되므로 등급은 "B"입니다. 검사를 반대 순서로 정렬했다면 70점 이상인 모든 점수가 "C"를 받았을 것입니다.

중괄호 함정: else는 어디에 와야 하는가

거의 모든 사람의 첫 R 스크립트를 물어뜯는 오류입니다. 스크립트에서는(또는 Rscript로 실행하는 무엇에서든) else앞 분기의 닫는 중괄호와 같은 줄에 나타나야 합니다. 다음은 실패합니다.

if (score >= 60) {
  print("You passed")
}
else {              # Error: unexpected 'else'
  print("Try again")
}

이유는 이렇습니다. R은 문장 단위로 파싱합니다. 줄 시작의 }에 도달하면 if 문은 문법적으로 완결되고 R은 그 자리에서 평가합니다. 다음 줄의 else는 새 문장의 시작으로 도착하는데, 문장은 else로 시작할 수 없습니다. 해결책은 이 페이지 전체에서 쓰는 형태입니다.

if (score >= 60) {
  print("You passed")
} else {            # brace and else on the same line
  print("Try again")
}

함수 본문이나 바깥 중괄호 안에서는 이 엄격한 규칙이 느슨해집니다(R이 바깥 중괄호가 닫힐 때까지 계속 읽기 때문입니다). 하지만 거기에 기대지 마세요. } else { 스타일은 어디서나 동작하고, R 스타일 가이드가 규정하는 방식입니다.

조건은 하나의 TRUE 또는 FALSE여야 합니다

if()는 정확히 하나의 논리값을 요구합니다. 이를 위반하는 두 가지가 있고, 둘 다 오류입니다.

if (NA) print("hi")
# Error: missing value where TRUE/FALSE needed

if (c(TRUE, FALSE)) print("hi")
# Error: the condition has length > 1

NA 경우는 실무에서 중요합니다. 결측 데이터와의 비교가 NA만들어 내기 때문입니다. xNA라면 x > 10NA이고, 그 조건을 받은 if는 스크립트를 멈춥니다. 방어적인 패턴은 단축 평가 &&를 사용합니다.

!is.na(x)FALSE이므로 x > 10 부분은 평가되지 않고 NA가 조건에 도달하지 않습니다. NA가 비교를 통해 전파되는 방식은 결측값에서 다룹니다.

길이가 1보다 크다는 오류는(R 4.2부터 강제되며, 그전에는 R이 조용히 첫 원소를 사용했습니다) 대개 다음 중 하나를 의도했다는 뜻입니다. 하나만 일치해도 되면 any(v > 5), 모든 원소가 통과해야 하면 all(v > 5), 원소별 답을 원했다면 ifelse()입니다. 다음 절이 바로 그것입니다.

ifelse(): 벡터화된 if else

if는 한 번 결정합니다. ifelse(test, yes, no)벡터의 모든 원소에 대해 결정하고 같은 길이의 벡터를 돌려줍니다.

temps의 각 원소가 독립적으로 검사됩니다. "hot" "mild" "mild" "hot" "mild"입니다. 기존 것에서 새로운 벡터나 데이터 프레임 열을 파생시키는 도구이며, 반복문이 필요 없습니다.

if와 달리 ifelse()는 결측값을 우아하게 처리합니다. 검사에 NA가 있으면 오류 대신 결과에 NA가 나옵니다.

세 갈래 분기를 위해 ifelse() 호출을 중첩할 수 있고, 그 깊이까지는 여전히 읽을 만합니다.

하지만 거기서 멈추세요. ifelse()를 세 번 이상 중첩하면 괄호 짝 맞추기 퍼즐이 됩니다. 그 시점에는 (수치 구간에는) cut()이나, 각 조건을 한 줄씩 늘어놓는 dplyr::case_when()을 쓰세요.

다중 분기를 위한 switch()

구간을 검사하는 것이 아니라 하나의 값을 알려진 이름 목록과 맞춰 보는 상황이라면, 긴 else if 연쇄는 어색한 도구입니다. switch()는 그것을 직접 표현합니다.

알아 둘 동작이 세 가지 있습니다.

  • 매칭: switch()는 문자 값을 인자 이름들과 비교해 일치하는 결과를 돌려줍니다.
  • 폴스루: 오른쪽이 비어 있는 이름(sat = ,)은 다음 경우의 결과로 넘어갑니다. "sat""sun"이 반복 없이 "weekend"를 공유하는 방법입니다.
  • 기본값: 마지막의 이름 없는 인자("weekday")가 아무것도 일치하지 않을 때 반환됩니다. 기본값이 없으면 일치하지 않는 값에 대해 switch()는 보이지 않게 NULL을 돌려주고, 여러분의 함수는 조용히 아무것도 반환하지 않게 됩니다. 헷갈리는 버그이니 항상 기본값을 주세요(또는 명시적으로 stop()을 두세요).

switch()는 모드나 메서드 인자에 따라 분기하는 함수 안에서 빛을 발합니다. 수치 임계값에 기반한 것이라면 else ifcut()을 쓰세요.

핵심 정리

  • if (condition) { } else { }는 조건을 괄호에 넣고 한 분기를 실행합니다. else if로 이어 붙이면 첫 일치가 이깁니다.
  • 스크립트에서는 } else {를 한 줄에 쓰세요. 줄 시작의 else는 문법 오류입니다.
  • if()는 정확히 하나의 TRUE/FALSE가 필요합니다. NA는 오류이고, 더 긴 벡터도 오류입니다(R 4.2부터). !is.na(x) &&로 방어하거나 any()/all()로 줄이세요.
  • ifelse(test, yes, no)는 벡터화된 버전입니다. 새 벡터를 계산할 때 쓰고, 두 번을 넘겨 중첩하지 마세요.
  • switch()는 이름에 따른 다중 분기를 처리하며, 빈 경우를 통한 폴스루를 지원합니다. 항상 기본값을 주세요.

다음 순서는 무언가를 한 번 이상 하는 방법입니다. for 반복문과, 반복문이 알맞은 도구인 때와 아닌 때를 다룹니다.

자주 묻는 질문

R에서 if else 문은 어떻게 작성하나요?

if (condition) { ... } else { ... } 형태로 씁니다. 조건은 괄호 안에, 각 분기는 중괄호 안에 둡니다. 추가 검사는 else if (condition)으로 이어 붙입니다. 스크립트에서는 else가 앞 분기의 닫는 중괄호와 같은 줄에 있어야 합니다(} else {). 그렇지 않으면 R이 unexpected 'else'를 보고합니다.

R에서 if와 ifelse()의 차이는 무엇인가요?

if는 정확히 하나의 TRUE/FALSE 값을 검사해 한 분기의 코드를 실행하는 제어 흐름 문장입니다. ifelse(test, yes, no)는 벡터화된 함수로, 벡터의 모든 원소를 한 번에 검사해 결과 벡터를 돌려줍니다. 프로그램이 무엇을 할지 결정할 때는 if를, 기존 열이나 벡터에서 새 것을 계산할 때는 ifelse()를 쓰세요.

R이 'the condition has length > 1'이라고 하는 이유는 무엇인가요?

하나의 TRUE나 FALSE가 필요한 if()에 벡터 전체를 넘겼기 때문입니다. R 4.2부터는 첫 원소를 조용히 사용하는 대신 오류가 납니다. 벡터를 하나의 값으로 줄이거나(any(x > 5), all(x > 5)), 원소별 결과를 원했다면 벡터화된 ifelse()로 바꾸어 해결하세요.

R에서 switch()는 어떻게 동작하나요?

switch(value, name1 = result1, name2 = result2, default)는 문자 값을 인자 이름들과 비교해 일치하는 결과를 돌려줍니다. 오른쪽이 비어 있는 이름은 다음 결과로 넘어가므로 여러 경우가 하나의 결과를 공유할 수 있습니다. 마지막의 이름 없는 인자가 기본값 역할을 하며, 기본값이 없으면 일치하지 않는 값은 보이지 않게 NULL을 돌려줍니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기