9. 묶음 처리, 반복문과 조건부 실행
9. 묶음 처리, 반복문과 조건부 실행
R에서 명령어는 "하나씩 실행"하는 것뿐 아니라, 중괄호로 묶어 하나의 표현식처럼 다루고, 조건에 따라 갈래를 나누고, 같은 작업을 반복하는 것까지 전부 가능해요. 이번 장에서는 그 핵심 도구인 그룹 표현식(Grouped expressions) 과 제어문(Control statements) 을 차례로 살펴볼게요.
출처: R 공식 매뉴얼
본문
9.1 그룹 표현식 (Grouped expressions)
R은 표현식 언어(expression language) 예요. R 안에서 실행되는 모든 명령은 어떤 결과를 돌려주는 함수나 표현식이라는 뜻이죠. 심지어 할당(assignment)도 하나의 표현식이며, 그 결과가 바로 "할당된 값"이에요. 그래서 할당은 표현식을 쓸 수 있는 어디든 등장할 수 있고, 특히 여러 번의 할당을 연달아 할 수도 있어요.
명령들은 중괄호 { } 안에 묶을 수 있어요.
{ expr_1; … ; expr_m }
이렇게 묶으면, 그룹 전체의 값은 마지막에 평가된 표현식의 결과가 돼요. 그리고 그룹 자체도 하나의 표현식이기 때문에, 예를 들어 다시 괄호로 감싸 더 큰 표현식의 일부로 쓰는 식으로 얼마든지 겹쳐 쓸 수 있어요.
9.2 제어문 (Control statements)
제어문은 크게 두 갈래로 나뉘어요.
- 조건부 실행:
if문 - 반복 실행:
for루프,repeat,while
9.2.1 조건부 실행: if 문
R에는 다음과 같은 형태의 조건문이 있어요.
if ( expr_1 ) expr_2 else expr_3
여기서 expr_1 은 단일 논리값 하나로 평가되어야 하고, 전체 표현식의 결과는 그에 따라 결정돼요.
if 문의 조건 안에서 자주 쓰이는 게 "단락(short-circuit) 연산자" 인 && 와 || 예요. 일반적인 & 와 | 는 벡터의 원소별로(element-wise) 적용되는 반면, && 와 || 는 길이 1짜리 벡터에만 적용되고, 꼭 필요할 때만 두 번째 인자를 평가한답니다. 그래서 "조건을 좌에서 우로 미리 검사하다가 결과가 정해지면 멈추는" 흐름을 만들 수 있어요.
한편 if/else 를 벡터 전체에 한 번에 적용하는 벡터화된 버전도 있어요. 바로 ifelse 함수예요.
ifelse(condition, a, b)
ifelse 는 condition 과 같은 길이의 벡터를 돌려주는데, condition[i] 가 참이면 a[i] 를, 아니면 b[i] 를 반환해요. (필요하면 a 와 b 는 재활용(recycling)돼요.)
9.2.2 반복 실행: for 루프, repeat, while
R에도 for 루프가 있어요.
for ( name in expr_1 ) expr_2
여기서 name 은 루프 변수예요. expr_1 은 벡터 표현식(흔히 1:20 같은 수열)이고, expr_2 는 대개 그룹 표현식으로, 하위 표현식들이 가짜 변수인 name 을 이용해 작성되죠. name 이 expr_1 의 결과 벡터의 값을 차례로 거쳐 가면서 expr_2 를 반복 평가해요.
예를 들어볼게요. ind 가 클래스(class)를 나타내는 지표(indicator) 벡터이고, 클래스별로 y 대비 x 의 플롯을 따로 그리고 싶다고 해볼게요. 한 가지 방법은 coplot() 을 쓰는 건데요 — 이건 요인의 각 수준에 대응하는 플롯 배열을 만들어 줘요. 또 다른 방법은 모든 플롯을 한 화면에 모으는 것인데, 아래처럼 하면 돼요.
> xc <- split(x, ind)
> yc <- split(y, ind)
> for (i in 1:length(yc)) {
plot(xc[[i]], yc[[i]])
abline(lsfit(xc[[i]], yc[[i]]))
}
이때 split() 함수에 주목할 필요가 있어요 — 요인으로 지정된 클래스에 따라 더 큰 벡터를 쪼개서 벡터들의 리스트를 만드는 함수랍니다. 꽤 유용한 함수로, 주로 상자그림(boxplot)과 함께 쓰여요. 자세한 내용은 도움말을 확인해 보세요.
⚠️ 주의: for() 루프는 컴파일 언어에서보다 R 코드에서 훨씬 덜 자주 쓰여요. 벡터 전체를 한꺼번에 다루는("whole object" 관점의) 코드가 R에서는 더 명확하고 더 빠르기 때문이에요.
그 밖의 반복 기능으로는 다음 두 가지 문이 있어요.
repeat 문:
repeat expr
while 문:
while ( condition ) expr
break문은 어떤 루프든 종료시킬 수 있어요. 특히repeat루프는 이것만으로만 끝낼 수 있어요.next문은 특정 한 번의 주기(한 번의 반복)만 중단하고 "다음" 반복으로 건너뛰는 데 써요.
제어문은 사실 함수와 함께 쓰일 때 가장 활발하게 등장해요. 이와 관련한 더 많은 예시는 다음 장인 "Writing your own functions"(직접 함수 작성하기)에서 다루게 될 거예요.
더 알아보기
- R 공식 매뉴얼 (An Introduction to R) — 이번 장은 R 언어의 기초 문법을 공식 문서의 목소리로 정리한 본문이에요.
?ifelse,?split,?for— R 도움말에서 각 함수의 세부 규칙과 예시를 바로 확인할 수 있어요.- 다음 장 "10 Writing your own functions"에서 실제 함수 정의 안에서 제어문이 어떻게 쓰이는지 이어서 살펴보면 좋아요.