12. 그래픽 절차
12. 그래픽 절차 (Graphical procedures)
R 환경에서 그래픽 기능은 굉장히 중요하면서도 쓸모가 다양해요. 이를 이용하면 아주 다양한 종류의 통계 그래프를 그릴 수 있을 뿐 아니라, 완전히 새로운 형태의 그래프까지 직접 만들어 낼 수 있답니다.
출처: R 공식 매뉴얼
본문
그래픽 기능은 대화형(interactive) 모드와 배치(batch) 모드 어디서든 쓸 수 있어요. 다만 대부분의 경우 대화형으로 쓰는 게 훨씬 생산적이에요. 대화형 사용이 쉬운 이유는, R이 시작될 때 그래픽 디바이스 드라이버(device driver) 를 자동으로 구동해 대화형 그래픽을 그릴 전용 그래픽 창을 열어 주기 때문이에요. 이 작업은 자동으로 이뤄지지만, 그 명령이 운영체제마다 다르다는 건 알아 두면 좋아요. UNIX 계열에서는 X11(), Windows에서는 windows(), macOS에서는 quartz()를 써요. 그리고 언제든 dev.new()로 새 디바이스를 열 수 있어요.
일단 디바이스 드라이버가 실행되면, R의 플롯팅 명령을 이용해 다양한 그래픽 화면을 만들고 완전히 새로운 종류의 화면도 만들어 낼 수 있어요.
플롯팅 명령은 크게 세 가지 기본 그룹으로 나뉘어요.
- 고수준(high-level) 플롯팅 함수는 그래픽 디바이스 위에 새 플롯을 만들면서, 필요하면 축·레이블·제목 등을 함께 그려 줘요.
- 저수준(low-level) 플롯팅 함수는 이미 존재하는 플롯에 추가 점, 선, 레이블 같은 정보를 더해 줘요.
- 대화형 그래픽 함수는 마우스 같은 포인팅 장치를 이용해, 기존 플롯에 정보를 추가하거나 플롯에서 정보를 추출할 수 있게 해 줘요.
거기에 더해 R은 그래픽 파라미터(graphical parameters) 목록을 관리하는데, 이걸 조작하면 플롯을 자기 취향대로 커스터마이즈할 수 있어요.
이 매뉴얼에서는 소위 '베이스(base)' 그래픽만 다뤄요. grid 패키지에는 베이스 그래픽과 함께 쓰이는 별도의 그래픽 하부 시스템이 있는데, 이건 더 강력하지만 쓰기도 더 어려워요. grid를 기반으로 S의 Trellis 시스템과 비슷한 다중 패널 플롯을 만들 수 있게 해 주는 권장 패키지로는 lattice가 있어요.
12.1 고수준 플롯팅 명령 (High-level plotting commands)
고수준 플롯팅 함수는 인자로 전달된 데이터의 '완전한' 플롯을 만들어 내도록 설계됐어요. 상황에 맞게 축, 레이블, 제목이 자동으로 생성돼요 (다른 걸 요청하지 않는 한요). 고수준 플롯팅 명령은 항상 새 플롯을 시작하며, 필요하면 현재 플롯을 지워요.
12.1.1 plot() 함수 (The plot() function)
R에서 가장 자주 쓰이는 플롯팅 함수 중 하나가 plot() 함수예요. 이 함수는 제네릭 함수(generic function) 인데, 그게 무슨 뜻이냐면, 만들어지는 플롯의 종류가 첫 번째 인자의 타입 혹은 클래스에 따라 달라진다는 거예요.
plot(x, y)
plot(xy)
x와 y가 벡터라면, plot(x, y)는 y를 x에 대응시켜 그린 산점도(scatterplot)를 만들어요. 두 번째 형태처럼 인자를 하나만 넘겨도 같은 결과가 나와요—이때는 x와 y라는 두 원소를 담은 리스트나, 두 개의 열을 가진 행렬을 넘기면 돼요.
plot(x)
x가 시계열(time series)이면 시계열 플롯을 그려요. x가 숫자형 벡터면, 벡터 안의 값을 그 인덱스(위치)에 대응시켜 그려요. x가 복소수 벡터면, 각 원소의 허수부를 실수부에 대응시켜 그려요.
plot(f)
plot(f, y)
f는 factor 객체, y는 숫자형 벡터예요. 첫 번째 형태는 f의 막대 플롯(bar plot)을 그려 주고, 두 번째 형태는 f의 각 수준(level)에 대해 y의 상자 그림(boxplot)을 그려 줘요.
plot(df)
plot(~ expr)
plot(y ~ expr)
df는 데이터 프레임, y는 어떤 객체든 가능하고, expr은 +로 구분한 객체 이름의 나열(예: a + b + c)이에요. 첫 두 형태는 데이터 프레임 안의 변수들(첫 형태) 또는 이름 붙은 여러 객체들(둘째 형태)의 분포 플롯을 만들어 줘요. 세 번째 형태는 expr에 나열된 각 객체에 대해 y를 대응시켜 그려요.
12.1.2 다변량 데이터 나타내기 (Displaying multivariate data)
R은 다변량 데이터를 표현하는 데 아주 유용한 함수 두 개를 제공해요. X가 숫자형 행렬이나 데이터 프레임이라면, 아래 명령으로
> pairs(X)
X의 각 열이 정의하는 변수들 사이의 쌍별 산점도 행렬(pairwise scatterplot matrix)을 만들 수 있어요. 즉 X의 모든 열을 다른 모든 열과 각각 대응시켜 그리는데, 그 결과 생기는 n(n-1)` 개의 플롯을 행렬처럼 배열하되, 행과 열에 걸쳐 플롯의 스케일이 일정하게 유지돼요.
변수가 세 개나 네 개일 때는 공변조건 플롯(coplot) 이 더 유용할 수 있어요. a와 b가 숫자형 벡터이고 c가 숫자형 벡터 또는 factor 객체(모두 같은 길이)라면, 다음 명령으로
> coplot(a ~ b | c)
c의 주어진 값들에 대해 a를 b에 대응시킨 산점도 여러 개를 만들어 줘요. c가 factor라면, c의 각 수준마다 a를 b에 대응시켜 그린다는 뜻이에요. c가 숫자형이면 여러 개의 조건 구간(conditioning interval)으로 나뉘고, 각 구간에 속하는 c 값들에 대해 a를 b에 대응시켜 그려요. 구간의 개수와 위치는 coplot()의 given.values= 인자로 조절할 수 있고, 구간을 고르는 데는 co.intervals() 함수가 유용해요. 조건 변수를 두 개 쓰는 것도 가능해요. 예를 들면
> coplot(a ~ b | c + d)
처럼 쓰면, c와 d의 결합 조건 구간마다 a를 b에 대응시킨 산점도를 만들어 줘요.
coplot()과 pairs() 함수는 둘 다 panel= 인자를 받는데, 이걸로 각 패널에 어떤 플롯을 그릴지 정할 수 있어요. 기본값은 points()라서 산점도를 그리지만, panel= 값으로 두 벡터 x와 y를 받는 다른 저수준 그래픽 함수를 넘겨 주면 원하는 어떤 플롯이든 만들 수 있어요. coplot에서 유용하게 쓰이는 패널 함수 예로는 panel.smooth()가 있어요.
12.1.3 표시용 그래픽 (Display graphics)
다른 고수준 그래픽 함수들은 서로 다른 종류의 플롯을 만들어 줘요. 몇 가지 예를 들면:
qqnorm(x)
qqline(x)
qqplot(x, y)
분포 비교 플롯이에요. 첫 형태는 숫자형 벡터 x를 기대 정규 순서 점수(expected Normal order scores)에 대응시켜 그리는 정규 점수 플롯(normal scores plot)이고, 둘째 형태는 그런 플롯 위에 분포의 사분위수와 데이터의 사분위수를 지나는 직선을 그려 줘요. 셋째 형태는 x의 분위수를 y의 분위수에 대응시켜 두 분포를 서로 비교해요.
hist(x)
hist(x, nclass=n)
hist(x, breaks=b, …)
숫자형 벡터 x의 히스토그램을 그려 줘요. 보통은 적절한 개수의 계급(class)이 자동으로 선택되는데, nclass= 인자로 추천 개수를 줄 수 있어요. 아니면 breaks= 인자로 분절점(breakpoint)을 정확히 지정해도 돼요. probability=TRUE 인자를 주면, 막대가 도수(count) 대신 상대 빈도를 구간 폭으로 나눈 값을 나타내요.
dotchart(x, …)
x 데이터의 점 도표(dot chart)를 만들어 줘요. 점 도표에서는 y축이 x 안의 데이터를 지시하는 레이블 역할을 하고, x축이 그 값을 나타내요. 예를 들어 특정 범위에 속하는 값을 가진 데이터 항목을 시각적으로 고르기 쉽게 해 줘요.
image(x, y, z, …)
contour(x, y, z, …)
persp(x, y, z, …)
세 변수의 플롯이에요. image 플롯은 서로 다른 색으로 z의 값을 표현하는 사각 격자를 그려 주고, contour 플롯은 z의 값을 표현하는 등고선을 그려 주며, persp 플롯은 3차원 표면을 그려 줘요.
12.1.4 고수준 플롯팅 함수의 인자 (Arguments to high-level plotting functions)
고수준 그래픽 함수에 넘길 수 있는 인자는 여러 가지가 있어요. 다음과 같아요.
add=TRUE
함수가 저수준 그래픽 함수처럼 동작하도록 강제해서, 현재 플롯 위에 새 플롯을 겹쳐 그려 줘요 (일부 함수만 지원해요).
axes=FALSE
축 생성이 억제돼요—axis() 함수로 나만의 축을 추가할 때 유용해요. 기본값 axes=TRUE는 축을 포함한다는 뜻이에요.
log="x"
log="y"
log="xy"
x축, y축, 또는 양쪽 축을 로그 스케일로 만들어 줘요. 많은 종류의 플롯에서 작동하지만 전부는 아니에요.
type=
type= 인자는 만들 플롯의 종류를 조절해요. 다음과 같아요.
type="p"
개별 점을 그려요 (기본값).
type="l"
선을 그려요.
type="b"
점과 그것을 잇는 선을 모두 그려요.
type="o"
점을 그 위에 선이 겹쳐지게 그려요.
type="h"
점에서 0축까지 수직선을 그려요 (고밀도, high-density).
type="s"
type="S"
계단 함수 플롯이에요. 첫 형태에서는 수직선의 위쪽이 점을 정의하고, 둘째 형태에서는 아래쪽이 점을 정의해요.
type="n"
아무것도 그리지 않아요. 다만 축은 (기본적으로) 여전히 그려지고, 좌표계는 데이터에 맞춰 설정돼요. 나중에 저수준 그래픽 함수로 플롯을 채울 때 이상적이에요.
xlab=string
ylab=string
x축과 y축의 축 레이블이에요. 기본 레이블(보통 고수준 플롯팅 함수 호출에서 쓴 객체의 이름)을 바꾸고 싶을 때 이 인자를 써요.
main=string
그림 제목이에요. 플롯 위쪽에 큰 글꼴로 배치돼요.
sub=string
부제목이에요. x축 바로 아래에 더 작은 글꼴로 배치돼요.
12.2 저수준 플롯팅 명령 (Low-level plotting commands)
때로는 고수준 플롯팅 함수가 정확히 원하는 종류의 플롯을 만들어 주지 못할 때가 있어요. 그럴 때는 저수준 플롯팅 명령으로 현재 플롯에 추가 정보(점, 선, 텍스트 등)를 더할 수 있어요.
더 유용한 저수준 플롯팅 함수 몇 가지는 다음과 같아요.
points(x, y)
lines(x, y)
현재 플롯에 점 또는 연결된 선을 추가해 줘요. plot()의 type= 인자를 이 함수들에도 넘길 수 있어요 (기본값은 points()에서 "p", lines()에서 "l"이에요).
text(x, y, labels, …)
x, y가 주는 점 위치에 텍스트를 추가해 줘요. 보통 labels는 정수 또는 문자 벡터이고, 이 경우 labels[i]가 점 (x[i], y[i])에 그려져요. 기본값은 1:length(x)예요.
참고: 이 함수는 흔히 다음과 같은 순서로 쓰여요.
> plot(x, y, type="n"); text(x, y, names)
그래픽 파라미터 type="n"이 점은 억제하면서 축은 설정해 주고, text() 함수가 문자 벡터 names가 지정한 특수 문자들을 점 자리에 채워 넣어 줘요.
abline(a, b)
abline(h=y)
abline(v=x)
abline(lm.obj)
기울기 b와 절편 a를 가진 직선을 현재 플롯에 추가해 줘요. h=y는 플롯을 가로지르는 수평선의 높이에 해당하는 y좌표를 지정하는 데 쓰고, v=x는 수직선의 x좌표를 지정하는 데 비슷하게 써요. 또 lm.obj처럼 길이 2인 coefficients 성분을 가진 리스트(모형 적합 함수의 결과 같은 것)를 넘기면, 그 둘을 순서대로 절편과 기울기로 해석해요.
polygon(x, y, …)
(x, y)에서 순서대로 주어진 꼭짓점으로 정의되는 다각형을 그리고, (선택적으로) 빗금으로 음영 처리하거나, 그래픽 디바이스가 도형 채우기를 지원하면 색으로 채워 줘요.
legend(x, y, legend, …)
지정한 위치에 범례(legend)를 추가해 줘요. 플로팅 문자, 선 스타일, 색 등이 문자 벡터 legend에 있는 레이블과 연결돼요. 또 legend와 같은 길이의 벡터 v를 값으로 가진 최소한 하나의 인자를 더 줘야 해요. 다음과 같이요.
legend( , fill=v)
채워진 상자의 색.
legend( , col=v)
점이나 선을 그릴 색.
legend( , lty=v)
선 스타일.
legend( , lwd=v)
선 너비.
legend( , pch=v)
플로팅 문자 (문자 벡터).
title(main, sub)
현재 플롯 위쪽에 큰 글꼴로 제목 main을, (선택적으로) 아래쪽에 더 작은 글꼴로 부제목 sub를 추가해 줘요.
axis(side, …)
첫 번째 인자가 주는 위치(아래쪽부터 시계 방향으로 1부터 4까지)에 축을 추가해 줘요. 다른 인자들은 축의 위치(플롯 안쪽 또는 바깥쪽)와 눈금 위치·레이블을 조절해요. axes=FALSE로 plot()을 호출한 뒤 나만의 축을 추가할 때 유용해요.
저수준 플롯팅 함수는 보통 새 플롯 요소를 어디에 놓을지 정하기 위해 위치 정보(예: x, y 좌표)가 필요해요. 좌표는 사용자 좌표(user coordinates) 로 주어지는데, 이는 이전 고수준 그래픽 명령이 정의하고 주어진 데이터에 기반해 선택된 것이에요.
x와 y 인자가 필요할 때, x와 y라는 이름의 원소를 가진 리스트 하나만 넘겨도 충분해요. 마찬가지로 두 개의 열을 가진 행렬도 유효한 입력이에요. 이런 방식 덕분에 아래에서 볼 locator() 같은 함수로 플롯 위의 위치를 대화형으로 지정할 수 있어요.
12.2.1 수학 주석 (Mathematical annotation)
어떤 경우에는 플롯에 수학 기호와 수식을 추가하는 게 유용해요. R에서는 text, mtext, axis, title 중 어느 곳에서든 문자 문자열 대신 표현식(expression) 을 지정하면 이걸 해낼 수 있어요. 예를 들어 아래 코드는 이항 확률 함수(Binomial probability function)의 공식을 그려 줘요.
> text(x, y, expression(paste(bgroup("(", atop(n, x), ")"), p^x, q^{n-x})))
이용 가능한 기능 전체 목록을 포함한 더 자세한 정보는 R 안에서 다음 명령으로 얻을 수 있어요.
> help(plotmath)
> example(plotmath)
> demo(plotmath)
12.2.2 Hershey 벡터 폰트 (Hershey vector fonts)
text와 contour 함수를 쓸 때 텍스트 렌더링에 Hershey 벡터 폰트를 지정할 수 있어요. Hershey 폰트를 쓰는 이유는 세 가지예요.
- Hershey 폰트는 특히 회전된 텍스트나 작은 텍스트에서 (컴퓨터 화면에서 특히) 더 나은 출력을 만들어 내요.
- Hershey 폰트는 표준 폰트에는 없을 수 있는 특정 기호를 제공해요. 특히 별자리 기호, 지도 제작 기호, 천문 기호가 있어요.
- Hershey 폰트는 키릴 문자와 일본 문자(Kana와 Kanji)를 제공해요.
Hershey 문자표를 포함한 더 자세한 정보는 R 안에서 다음 명령으로 얻을 수 있어요.
> help(Hershey)
> demo(Hershey)
> help(Japanese)
> demo(Japanese)
12.3 그래픽과 상호작용하기 (Interacting with graphics)
R은 마우스로 플롯에서 정보를 추출하거나 플롯에 정보를 추가할 수 있게 해 주는 함수도 제공해요. 그중 가장 간단한 것이 locator() 함수예요.
locator(n, type)
사용자가 왼쪽 마우스 버튼으로 현재 플롯 위의 위치를 선택할 때까지 기다려요. 이 과정은 n개(기본값 512)의 점이 선택되거나 다른 마우스 버튼이 눌릴 때까지 계속돼요. type 인자는 선택된 점에 플로팅을 할지 결정하며, 고수준 그래픽 명령에서와 같은 효과를 가져요. 기본값은 아무것도 그리지 않는 거예요. locator()는 선택된 점들의 위치를 x와 y라는 두 성분을 가진 리스트로 반환해요.
locator()는 보통 인자 없이 호출돼요. 그래픽 요소(범례나 레이블 같은)를 어디에 놓을지 미리 계산하기 어려울 때, 그 위치를 대화형으로 고르는 데 특히 유용해요. 예를 들어 바깥쪽으로 벗어난 점(이상치) 근처에 설명 텍스트를 놓으려면 다음 명령이 유용할 수 있어요.
> text(locator(1), "Outlier", adj=0)
(locator()는 현재 디바이스가 대화형 포인팅을 지원하지 않으면, 가령 postscript 같은 경우, 무시돼요.)
identify(x, y, labels)
사용자가 (왼쪽 마우스 버튼으로) x와 y가 정의하는 점 중 아무거나 골라서, 그 점 근처에 labels의 해당 성분(또는 labels가 없으면 점의 인덱스 번호)을 그려 강조할 수 있게 해 줘요. 다른 버튼을 누르면 선택된 점들의 인덱스를 반환해요.
때로는 플롯에서 특정 점을 그 위치가 아니라 '어떤 점인지'로 식별하고 싶을 때가 있어요. 예를 들어 그래픽 표시에서 관심 있는 관측값을 사용자가 고르게 한 다음, 그 관측값을 어떤 방식으로든 조작하고 싶을 수 있죠. 숫자형 벡터 두 개 x와 y로 주어진 여러 (x, y) 좌표가 있을 때, identify() 함수를 다음과 같이 쓸 수 있어요.
> plot(x, y)
> identify(x, y)
identify() 함수는 스스로 아무것도 그리지 않고, 다만 사용자가 마우스 포인터를 움직여 점 근처에서 왼쪽 마우스 버튼을 클릭하게 해 줘요. 마우스 포인터 근처에 점이 있으면, 그 점에 그 인덱스 번호(즉 x/y 벡터 안에서의 위치)가 근처에 그려져 표시돼요. 아니면 identify()의 labels 인자로 identify()를 사용해 어떤 정보 문자열(예: 케이스 이름)을 강조 표시로 쓸 수도 있고, plot=FALSE 인자로 표시를 아예 끌 수도 있어요. 그 과정이 (위에서 설명한 대로) 종료되면 identify()는 선택된 점들의 인덱스를 반환하고, 이 인덱스로 원래 벡터 x와 y에서 선택된 점들을 추출할 수 있어요.
12.4 그래픽 파라미터 사용하기 (Using graphics parameters)
특히 발표나 출판을 위한 그래픽을 만들 때, R의 기본값이 항상 정확히 필요한 결과를 내 주는 건 아니에요. 하지만 그래픽 파라미터를 이용하면 표시의 거의 모든 측면을 커스터마이즈할 수 있어요. R은 많은 개수의 그래픽 파라미터 목록을 관리하는데, 이들은 선 스타일, 색, 그림 배치, 텍스트 정렬 등 다양한 것을 조절해요. 모든 그래픽 파라미터는 이름(예: 색을 조절하는 'col')과 값(예: 색 번호)을 가져요.
각 활성 디바이스마다 별도의 그래픽 파라미터 목록이 유지되고, 각 디바이스는 초기화될 때 기본 파라미터 세트를 갖게 돼요. 그래픽 파라미터는 두 가지 방식으로 설정할 수 있어요. 영구적으로—현재 디바이스에 접근하는 모든 그래픽 함수에 영향을 주는 방식이거나, 일시적으로—단 한 번의 그래픽 함수 호출에만 영향을 주는 방식이에요.
12.4.1 영구 변경: par() 함수 (Permanent changes: The par() function)
par() 함수는 현재 그래픽 디바이스의 그래픽 파라미터 목록에 접근하고 수정하는 데 쓰여요.
par()
인자 없이 쓰면, 현재 디바이스의 모든 그래픽 파라미터와 그 값을 리스트로 반환해요.
par(c("col", "lty"))
문자 벡터를 인자로 주면, 이름이 지정된 그래픽 파라미터만 (역시 리스트로) 반환해요.
par(col=4, lty=2)
이름 붙은 인자(또는 하나의 리스트 인자)로 쓰면, 지정된 그래픽 파라미터의 값을 설정하고, 파라미터의 원래 값들을 리스트로 반환해요.
par() 함수로 그래픽 파라미터를 설정하면 파라미터의 값이 영구적으로 바뀌어요. 즉 (현재 디바이스에서) 이후의 모든 그래픽 함수 호출이 새 값의 영향을 받아요. 이런 방식의 설정은 파라미터의 '기본값'을 정한다고 생각하면 돼요—다른 값을 주지 않는 한 모든 그래픽 함수가 이 기본값을 사용해요.
par() 호출은 함수 안에서 이뤄지더라도 항상 그래픽 파라미터의 전역 값에 영향을 준다는 점에 주의하세요. 이는 종종 바람직하지 않은 동작이에요—보통은 그래픽 파라미터 몇 개를 설정하고, 플로팅을 좀 하고, 그다음 원래 값으로 복원해서 사용자의 R 세션에 영향을 주지 않게 하고 싶잖아요. 변경할 때 par()의 결과를 저장해 두고, 플로팅이 끝났을 때 원래 값으로 복원하면 초기 값을 되돌릴 수 있어요.
> oldpar <- par(col=4, lty=2)
... plotting commands ...
> par(oldpar)
설정 가능한24 그래픽 파라미터를 전부 저장했다 복원하려면 다음을 쓰세요.
> oldpar <- par(no.readonly=TRUE)
... plotting commands ...
> par(oldpar)
12.4.2 일시 변경: 그래픽 함수의 인자 (Temporary changes: Arguments to graphics functions)
그래픽 파라미터는 (거의) 어떤 그래픽 함수에든 이름 붙은 인자로 넘길 수도 있어요. 이는 그 인자를 par() 함수에 넘기는 것과 같은 효과를 주지만, 변경이 함수 호출 동안에만 지속된다는 점이 달라요. 예를 들어
> plot(x, y, pch="+")
는 플로팅 문자로 플러스 기호를 쓴 산점도를 만들어 주는데, 이후 플롯의 기본 플로팅 문자는 바꾸지 않아요.
아쉽게도 이 방식이 완전히 일관되게 구현돼 있지는 않아서, 그래픽 파라미터를 설정했다 되돌리는 데 par()를 써야 하는 경우가 때로 필요해요.
12.5 그래픽 파라미터 목록 (Graphics parameters list)
다음 절들에서는 흔히 쓰이는 그래픽 파라미터를 자세히 다뤄요. par() 함수의 R 도움말 문서가 더 간결한 요약을 제공하는데, 여기서는 그에 비해 좀 더 자세한 버전을 제공해요.
그래픽 파라미터는 다음 형태로 제시돼요.
name=value
파라미터의 효과에 대한 설명. name은 파라미터의 이름, 즉 par()나 그래픽 함수 호출에서 쓸 인자 이름이에요. value는 파라미터를 설정할 때 쓸 수 있는 전형적인 값이에요.
axes는 그래픽 파라미터가 아니라 몇몇 plot 메서드의 인자라는 점에 주의하세요. xaxt와 yaxt를 보세요.
12.5.1 그래픽 요소 (Graphical elements)
R 플롯은 점, 선, 텍스트, 다각형(채워진 영역)으로 구성돼요. 이 그래픽 요소들이 어떻게 그려지는지 제어하는 그래픽 파라미터가 있는데, 다음과 같아요.
pch="+"
점을 플로팅할 때 쓸 문자. 기본값은 그래픽 드라이버에 따라 다르지만, 보통 원이에요. 플롯된 점은 플로팅 문자로 "."를 쓰지 않는 한 해당 위치보다 약간 위나 아래에 나타나는 경향이 있어요. "."를 쓰면 정확히 중심에 찍혀요.
pch=4
pch를 0에서 25 사이의 정수로 주면, 전문화된 플로팅 기호가 만들어져요. 기호가 어떤 건지 보려면 다음 명령을 써 보세요.
> legend(locator(1), as.character(0:25), pch = 0:25)
21에서 25까지는 앞선 기호와 겹쳐 보일 수 있지만, 서로 다른 방식으로 색칠할 수 있어요. points 도움말과 그 예시를 참고하세요.
게다가 pch는 현재 폰트의 한 문자를 나타내는 문자이거나 32:255 범위의 숫자일 수도 있어요.
lty=2
선 타입. 대안적인 선 스타일은 모든 그래픽 디바이스에서 지원되지는 않고 (지원되는 곳에서도 서로 다르지만), 선 타입 1은 항상 실선이고, 선 타입 0은 항상 안 보이며, 선 타입 2 이후는 점선 또는 파선, 혹은 그 둘의 조합이에요.
lwd=2
선 너비. '표준' 선 너비의 배수로 표현한 원하는 선 너비. lines() 등으로 그린 선뿐 아니라 축 선에도 영향이 있어요. 모든 디바이스가 지원하는 건 아니고, 일부는 사용할 수 있는 너비에 제한이 있어요.
col=2
점, 선, 텍스트, 채워진 영역, 이미지에 쓸 색. 현재 팔레트(?palette 참고)에서 고른 숫자이거나 이름 붙은 색이에요.
col.axis
col.lab
col.main
col.sub
각각 축 주석, x·y 레이블, main 제목, sub 제목에 쓸 색.
font=2
텍스트에 어떤 글꼴을 쓸지 지정하는 정수. 가능하면 디바이스 드라이버가 1을 보통 텍스트로, 2를 볼드체로, 3을 이탤릭체로, 4를 볼드 이탤릭체로, 5를 (그리스 문자를 포함한) 기호 폰트로 배치해요.
font.axis
font.lab
font.main
font.sub
각각 축 주석, x·y 레이블, main 제목, sub 제목에 쓸 글꼴.
adj=-0.1
플로팅 위치에 대한 텍스트의 정렬. 0은 왼쪽 정렬, 1은 오른쪽 정렬, 0.5는 플로팅 위치를 기준으로 가로로 중앙 정렬을 의미해요. 실제 값은 플로팅 위치 왼쪽에 나타나는 텍스트의 비율이므로, -0.1 값은 텍스트와 플로팅 위치 사이에 텍스트 폭의 10%만큼의 틈을 남겨요.
cex=1.5
문자 확장(character expansion). 플로팅 문자를 포함한 텍스트 문자의 원하는 크기를 기본 텍스트 크기에 대한 상대값으로 나타낸 값이에요.
cex.axis
cex.lab
cex.main
cex.sub
각각 축 주석, x·y 레이블, main 제목, sub 제목에 쓸 문자 확장.
12.5.2 축과 눈금 (Axes and tick marks)
R의 고수준 플롯 대부분은 축을 가지며, 저수준 그래픽 함수 axis()로 직접 축을 만들 수도 있어요. 축은 세 가지 주요 구성 요소로 이뤄져요. 축 선(선 스타일은 lty 그래픽 파라미터로 제어), 눈금(tick marks, 축 선을 따라 단위 구간을 표시), 눈금 레이블(tick labels, 단위를 표시). 이 구성 요소들은 다음 그래픽 파라미터로 커스터마이즈할 수 있어요.
lab=c(5, 7, 12)
처음 두 숫자는 각각 x축과 y축에 원하는 눈금 구간 수예요. 세 번째 숫자는 소수점을 포함한 문자의 수로 나타낸 축 레이블의 원하는 길이. 이 파라미터에 너무 작은 값을 고르면 모든 눈금 레이블이 같은 숫자로 반올림돼 버릴 수 있어요!
las=1
축 레이블의 방향. 0은 항상 축에 평행, 1은 항상 수평, 2는 항상 축에 수직을 의미해요.
mgp=c(3, 1, 0)
축 구성 요소의 위치. 첫 번째 성분은 축 레이블에서 축 위치까지의 거리를 텍스트 줄 수로 나타낸 값이에요. 두 번째 성분은 눈금 레이블까지의 거리이고, 마지막 성분은 축 위치에서 축 선까지의 거리(보통 0)예요. 양수는 플롯 영역 바깥쪽, 음수는 안쪽을 잰 값이에요.
tck=0.01
눈금의 길이를 플로팅 영역 크기의 분수로 나타낸 값. tck가 작으면(0.5보다 작으면) x축과 y축의 눈금이 같은 크기가 되도록 강제돼요. 1 값은 격자선을 주고, 음수 값은 플로팅 영역 바깥쪽에 눈금을 놓아요. 내부 눈금을 쓰려면 tck=0.01과 mgp=c(1,-1.5,0)을 사용하세요.
xaxs="r"
yaxs="i"
각각 x축과 y축의 축 스타일. "i"(internal)와 "r"(기본값) 스타일에서는 눈금이 항상 데이터 범위 안에 들어오는데, "r" 스타일은 가장자리에 약간의 여백을 남겨요.
12.5.3 그림 여백 (Figure margins)
R에서 하나의 플롯은 그림(figure) 이라고 불리고, 여백(축 레이블, 제목 등을 담을 수 있는)으로 둘러싸인 플롯 영역(plot region) 으로 이뤄지며, (보통) 축 자체로 경계가 지어져요.
전형적인 그림이 어떤 모양인지 보여 주는 그림은 다음과 같아요 (원문의 그림 참고).
그림 배치를 제어하는 그래픽 파라미터는 다음과 같아요.
mai=c(1, 0.5, 0.5, 0)
각각 아래, 왼쪽, 위, 오른쪽 여백의 너비를 인치 단위로 나타낸 값.
mar=c(4, 2, 2, 1)
mai와 비슷하지만, 측정 단위가 텍스트 줄 수라는 점이 달라요.
mar와 mai는 서로 등가예요. 하나를 설정하면 다른 하나의 값도 바뀌어요. 이 파라미터에 고른 기본값은 종종 너무 커요. 오른쪽 여백은 거의 필요 없고, 제목을 쓰지 않는다면 위쪽 여백도 마찬가지예요. 아래쪽과 왼쪽 여백은 축과 눈금 레이블을 수용할 만큼 충분히 커야 해요. 게다가 기본값은 디바이스 표면의 크기를 고려하지 않고 선택돼요. 예를 들어 postscript() 드라이버를 height=4 인자로 쓰면, mar나 mai를 명시적으로 설정하지 않는 한 여백이 약 50%인 플롯이 나와요. 여러 그림을 쓸 때(아래 참고) 여백은 줄어들지만, 한 페이지에 많은 그림을 놓을 때는 그걸로 부족할 수 있어요.
12.5.4 다중 그림 환경 (Multiple figure environment)
R은 한 페이지에 n×m 배열의 그림을 만들 수 있게 해 줘요. 각 그림은 자기만의 여백을 가지며, 그림 배열은 선택적으로 바깥 여백(outer margin)으로 둘러싸여요 (아래 그림 참고).
다중 그림과 관련된 그래픽 파라미터는 다음과 같아요.
mfcol=c(3, 2)
mfrow=c(2, 4)
다중 그림 배열의 크기를 설정해요. 첫 번째 값은 행의 수, 두 번째 값은 열의 수예요. 이 두 파라미터의 유일한 차이는 mfcol은 그림을 열 단위로 채우고 mfrow는 행 단위로 채운다는 점이에요.
(원문 그림 참고) 그림의 배치는 mfrow=c(3,2)를 설정해서 만들어진 것으로, 네 개의 플롯을 그린 뒤의 페이지를 보여 줘요.
둘 중 하나를 설정하면 기호와 텍스트의 기본 크기(par("cex")와 디바이스의 pointsize가 제어)를 줄일 수 있어요. 정확히 행과 열이 두 개씩인 배치에서는 기본 크기가 0.83 배율로 줄어들고, 행이나 열이 셋 이상이면 0.66 배율로 줄어들어요.
mfg=c(2, 2, 3, 2)
다중 그림 환경에서 현재 그림의 위치. 처음 두 숫자는 현재 그림의 행과 열이고, 마지막 두 숫자는 다중 그림 배열의 행과 열 수예요. 이 파라미터를 설정해 배열 안의 그림 사이를 점프할 수 있어요. 같은 페이지에 크기가 서로 다른 그림을 그릴 때는 마지막 두 숫자에 실제 값과 다른 값을 쓸 수도 있어요.
fig=c(4, 9, 1, 4)/10
페이지에서 현재 그림의 위치. 값은 각각 왼쪽, 오른쪽, 아래, 위 가장자리의 위치를 페이지의 백분율로, 페이지의 왼쪽 아래 모서리에서 잰 값이에요. 예시 값은 페이지의 오른쪽 아래에 있는 그림에 해당해요. 이 파라미터를 설정하면 페이지 안에서 그림을 임의로 배치할 수 있어요. 현재 페이지에 그림을 추가하려면 (S와는 달리) new=TRUE도 함께 써야 해요.
oma=c(2, 0, 3, 0)
omi=c(0, 0, 0.8, 0)
바깥 여백의 크기. mar와 mai처럼, 첫 번째는 텍스트 줄 수로, 두 번째는 인치로, 아래쪽 여백부터 시작해 시계 방향으로 잽니다.
바깥 여백은 페이지 단위의 제목 등을 만드는 데 특히 유용해요. 바깥 여백에 텍스트를 추가하려면 outer=TRUE 인자를 가진 mtext() 함수를 쓰면 돼요. 다만 기본적으로 바깥 여백은 없으므로, oma나 omi로 명시적으로 만들어 줘야 해요.
더 복잡한 다중 그림 배치는 split.screen()과 layout() 함수로 만들 수 있고, grid와 lattice 패키지로도 만들 수 있어요.
12.6 디바이스 드라이버 (Device drivers)
R은 거의 모든 종류의 디스플레이나 프린팅 디바이스에서 (품질은 제각각이지만) 그래픽을 만들어 낼 수 있어요. 다만 그 전에 R이 어떤 종류의 디바이스를 다루는지 알아야 해요. 이건 디바이스 드라이버를 시작해서 이뤄져요. 디바이스 드라이버의 목적은 R의 그래픽 지시(예: "선을 그려라")를 해당 디바이스가 이해할 수 있는 형태로 변환하는 거예요.
디바이스 드라이버는 디바이스 드라이버 함수를 호출해서 시작돼요. 각 드라이버마다 함수가 하나씩 있는데, 전체 목록은 help(Devices)를 쳐 보세요. 예를 들어 다음 명령을 내리면
> postscript()
이후의 모든 그래픽 출력이 PostScript 형식으로 프린터로 보내져요. 흔히 쓰는 디바이스 드라이버 몇 가지는 다음과 같아요.
X11()
Unix 계열의 X11 윈도우 시스템에서 쓰기 위한 것.
windows()
Windows에서 쓰기 위한 것.
quartz()
macOS에서 쓰기 위한 것.
postscript()
PostScript 프린터로 인쇄하거나 PostScript 그래픽 파일을 만들기 위한 것.
pdf()
PDF 파일을 만들어 내며, 다른 PDF 파일에 포함시킬 수도 있어요.
png()
비트맵 PNG 파일을 만들어 내요. (항상 사용 가능한 건 아니에요. 도움말 페이지를 보세요.)
jpeg()
비트맵 JPEG 파일을 만들어 내며, 이미지 플롯에 가장 잘 쓰여요. (항상 사용 가능한 건 아니에요. 도움말 페이지를 보세요.)
디바이스 사용을 끝냈다면, 반드시 다음 명령으로 디바이스 드라이버를 종료해야 해요.
> dev.off()
이렇게 해야 디바이스가 깔끔하게 마무리돼요. 예를 들어 하드카피 디바이스의 경우 모든 페이지가 완성되어 프린터로 보내졌는지 보장해 줘요. (세션이 정상적으로 끝나면 자동으로 이뤄져요.)
12.6.1 조판 문서를 위한 PostScript 다이어그램 (PostScript diagrams for typeset documents)
postscript() 디바이스 드라이버 함수에 file 인자를 넘기면 그래픽을 PostScript 형식으로 원하는 파일에 저장할 수 있어요. horizontal=FALSE 인자를 주지 않으면 플롯은 가로(landscape) 방향이 되고, width와 height 인자로 그래픽 크기를 조절할 수 있어요 (이 치수에 맞게 플롯이 적절히 스케일링돼요). 예를 들어 다음 명령은
> postscript("file.ps", horizontal=FALSE, height=5, pointsize=10)
높이가 5인치인 그림의 PostScript 코드를 담은 파일을 만들고, 아마 문서에 포함하기 위해 쓰일 거예요. 명령에서 지정한 파일이 이미 존재한다면 덮어쓴다는 점을 꼭 기억하세요. 같은 R 세션의 앞부분에서 방금 만들었던 파일이라 해도 마찬가지예요.
PostScript 출력의 많은 용도는 그 그림을 다른 문서에 통합하는 거예요. 이때는 캡슐화된 PostScript(encapsulated PostScript) 를 만들 때 가장 잘 작동해요. R은 항상 호환 가능한 출력을 만들어 내지만, onefile=FALSE 인자를 줄 때만 출력을 그런 것으로 표시해요. 이 특이한 표기는 S와의 호환성에서 나온 건데, 실제 뜻은 출력이 단일 페이지가 된다는 것이에요 (이는 EPSF 사양의 일부예요). 따라서 포함용 플롯을 만들려면 대략 이렇게 하세요.
> postscript("plot1.eps", horizontal=FALSE, onefile=FALSE,
height=8, width=6, pointsize=10)
12.6.2 여러 그래픽 디바이스 (Multiple graphics devices)
R을 고급으로 쓸 때는 여러 그래픽 디바이스를 동시에 사용하는 게 종종 유용해요. 물론 한 번에 그래픽 명령을 받아들일 수 있는 디바이스는 하나뿐이고, 그것을 현재 디바이스(current device) 라고 불러요. 여러 디바이스가 열려 있으면, 각 위치에 어떤 종류의 디바이스인지 알려 주는 이름을 가진, 번호가 매겨진 순서를 이뤄요.
다중 디바이스를 다룰 때 쓰는 주요 명령과 그 의미는 다음과 같아요.
X11() [UNIX]
windows() [Windows]
win.printer()
win.metafile()
quartz() [macOS]
postscript() [기타]
pdf()
png()
jpeg()
tiff()
bitmap()
…
디바이스 드라이버 함수를 새로 호출할 때마다 새 그래픽 디바이스가 열리고, 그래서 디바이스 목록이 1만큼 늘어나요. 이 디바이스가 현재 디바이스가 되어 그래픽 출력이 그곳으로 보내져요.
dev.list()
활성 디바이스 전부의 번호와 이름을 반환해요. 목록에서 위치 1에 있는 디바이스는 항상 그래픽 명령을 전혀 받지 않는 null 디바이스예요.
dev.next()
dev.prev()
각각 현재 디바이스의 다음 또는 이전에 있는 그래픽 디바이스의 번호와 이름을 반환해요.
dev.set(which=k)
현재 그래픽 디바이스를 디바이스 목록의 위치 k에 있는 것으로 바꾸는 데 쓸 수 있어요. 디바이스의 번호와 레이블을 반환해요.
dev.off(k)
디바이스 목록의 위치 k에 있는 그래픽 디바이스를 종료해요. postscript 같은 일부 디바이스의 경우, 디바이스를 어떻게 시작했느냐에 따라 파일을 즉시 인쇄하거나 나중에 인쇄할 수 있도록 파일을 올바르게 완성해요.
dev.copy(device, …, which=k)
dev.print(device, …, which=k)
디바이스 k의 복사본을 만들어요. 여기서 device는 postscript 같은 디바이스 함수이고, 필요하면 추가 인자는 '…'로 지정해요. dev.print는 비슷하지만, 복사된 디바이스가 즉시 닫혀서 하드카피 인쇄 같은 종료 동작이 즉시 수행돼요.
graphics.off()
목록에 있는 모든 그래픽 디바이스를 null 디바이스를 제외하고 전부 종료해요.
12.7 동적 그래픽 (Dynamic graphics)
R에는 점 구름 회전("rotating point clouds")이나 점 "브러싱"(대화형 강조 표시) 같은 동적 혹은 대화형 그래픽 기능이 내장돼 있지 않아요. 하지만 Swayne, Cook, Buja가 만든 GGobi 시스템에 방대한 동적 그래픽 기능이 있고,
R에서 이걸 rggobi 패키지를 통해 접근할 수 있어요. 자세한 내용은
에서 확인할 수 있어요.
또한 rgl 패키지는 예를 들어 표면 같은 3D 플롯과 상호작용하는 방법을 제공해요.
더 알아보기
- 이 챕터의 원문: R 공식 매뉴얼 — 12 Graphical procedures
- 플롯팅 함수 전체 목록은 R 안에서
help(Devices)로, 그래픽 파라미터 요약은?par로 확인할 수 있어요. - 베이스 그래픽보다 더 강력한
grid그래픽 하부 시스템과, 그 위에 다중 패널 플롯을 제공하는 lattice 패키지도 함께 알아 두면 좋아요. - 3D 대화형 그래픽에는 rgl, 동적 그래픽에는 GGobi(http://ggobi.org/)와 rggobi를 참고하세요.