지난번 포스팅에서는 R Base Package의 Graphics plotting system의
(1) 높은 수준의 그래프 함수 (high level graphic functions)
(2) 그래프 모수를 설정하는 2가지 방법 (2 methods of setting graphic parameters)
(3) 그래프 모수 : 기호(symbol), 선(line)
(4) 그래프 모수 : 색깔(color)
에 대해서 알아보았습니다. 이번 포스팅에서는
(5) 그래프 모수 : 그래프 영역 (plot area, inner margin area, outer margin area, multiple plot layout) 에 대해서 소개하도록 하겠습니다.
그래프 영역은 크게 (1) 그래프 영역 (plot area), (2) 내부 마진 영역 (inner margin area), (3) 외부 마진 영역(outer margin area) 로 구분할 수 있습니다. 아래의 예시 그래프에 각 영역의 위치에 text 로 표기를 해보았습니다.
[ 그래프 영역 및 내부/외부 마진 영역 (plot area and inner/outer margin area) ]
- 그래프 영역 (plot area), 내부 마진 영역 (inner margin area)
(1) 그래프 영역 (plot area)는 점이든 선이든 기호가 그려지는 영역입니다.
(2) 내부 마진 영역 (inner margin area)는 plot area를 감싸고 있는 4개 모서리 부분의 마진입니다. 하단 부분이 1번, 왼쪽 부분이 2번, 상단부분이 3번, 오른쪽 부분이 4번이며, 순서대로 내부 마진 영역의 디폴트 값은 c(5.1, 4.1, 4.1, 2.1) 입니다. 하단은 x축 label, 왼쪽은 y축 label, 상단은 제목이 들어가는 영역이다 보니 디폴트 값의 마진 숫자가 큰 반면에, 오른쪽은 보통은 label이 없으므로 디폴트 마진 값이 타 영역의 반절밖에 안됩니다.
> ##-------------------------------------------
> ## Graph Area and Outer/Inner Margin
> ##-------------------------------------------
>
> library(MASS) # to use Cars93 dataframe
>
> # plotting by default par setting of plot area and inner margin area > # default inner margin area : c(5.1, 4.1, 4.1, 2.1) >
> plot(MPG.highway ~ Weight, Cars93, type="p",
+ xlab = "Inner Margin Area 1",
+ ylab = "Inner Margin Area 2",
+ main = "Inner Margin Area 3")
>
> mtext("Inner Margin Area 4", side = 4)
>
> text(3000, 35, cex = 3, labels = "Plot Area", pos = 3)
|
- 외부 마진 영역 (outer margin area)
외부 마진 영역은 내부 마진 영역의 바깥 쪽을 둘러싸는 마진 영역이며, 내부 마진 영역과 위치 순서는 똑같이 하단 부분이 1번, 왼쪽 부분이 2번, 상단 부분이 3번, 오른쪽 부분이 4번입니다. 1번, 2번, 3번, 4번 별로 디폴트 마진 값은 c(0, 0, 0, 0) 입니다. 즉 위의 예의 경우 외부 마진(outer margin) 을 별도로 지정해주지 않았으므로 디폴트 값이 적용되어 외부 마진(outer margin)은 모두 '0' 으로 없는 셈입니다.
외부 마진 영역은 위의 예처럼 1개짜리 그래프에서는 별 쓸모가 없습니다만 (그냥 내부 마진 영역으로 cover 되기 때문입니다), 그래프 영역을 분할해서 2개 이상의 그래프를 하나의 그래프에 결합할 경우 유용하게 사용할 수 있습니다. 개별 그래프에서는 내부 마진 영역에 제목, x축 label, y축 label을 적고, 2개 이상의 개별 그래프들을 모두 아우리는 대제목 (mega title)을 적고자 할 때 외부 마진 영역에 적으면 딱 좋습니다.
아래에 1개의 row, 2개의 column으로 영역을 분할(mfrow = )한 경우 외부 마진 영역 설정(oma = ), 내부 마진 영역 설정(mar = ) 함수의 예를 들어보겠습니다. 외부 마진 부분은 파란색으로 알아보기 쉽게 위치 표시를 했습니다.
참고로, op <- par(no.readonly = TRUE) 로 디폴트 par 값을 미리 할당해두면 나중에 par 값 조정 다 끝나고 원래의 디폴트 값으로 되돌아오고자 할 때 par(op)를 실행시키면 되므로 매우 편리합니다.
> ## -- inner margin area, outer margin area
> # Save default par values, for resetting later
> op <- par(no.readonly = TRUE)
>
> # Change par() function options
> par(mfrow=c(1,2), # make frame by 1 row, 2 columns
+ mar=c(4, 3, 3, 1), # inner margin
+ oma=c(0.5, 0.5, 2, 0.5)) # outer margin
>
> # plot area, inner margin area, outer margin area
> plot(MPG.highway ~ Weight, Cars93, type="p",
+ xlab = "Inner Margin Area",
+ main = "Inner Margin Area")
>
> plot(MPG.highway ~ Horsepower, Cars93, type="p",
+ xlab = "Inner Margin Area",
+ main = "Inner Margin Area")
>
> mtext("Outer Margin Area", outer = TRUE, cex = 2, col = "blue") # outer = TRUE : outer margin area
>
>
> # Reset par to the default values at startup
> par(op)
|
- 영역 분할/결합 방법 1 : par(mfrow = ), par(mfcol = )
2개 이상의 다수의 그래프를 결합하는 방법에는 par() 함수와 layout() 함수의 2가지 방법이 있습니다. 먼저 par() 방법을 살펴보면, par(mfrow = ), par(mfcol = ) 의 2가지 모수 설정 방법이 있습니다. mfrow와 mfcol 은 아래의 말을 줄여 쓴 말입니다.
- mfrow : number of Multiple Figures (use ROW-wise)
- mfcol : number of Multiple Figures (use COLUMN-wise)
어렵지 않은 개념이므로 아래에 실제 예를 보면 바로 이해가 될 것이라고 봅니다. par(mfrow = c(4, 2)) 로 해서 4개 row, 2개 column으로 창을 분할해서 총 8개의 그래프를 결합한 예입니다. 그래프가 그려지는 순서를 화살표로 표시를 해두었는데요, 상단 왼쪽에서 시작해서 오른쪽으로 지그재그로 하단으로 내려가면서 그래프가 순차적으로 그려집니다.
> ##-- par(mfrow = ): multiple figures (use ROW-wise)
> par(mfrow=c(4, 2), # make window by 4 row, 2 columns
+ mar=c(4, 3, 3, 1), # inner margin
+ oma=c(0.5, 0.5, 2, 0.5)) # outer margin
>
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 1")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 2")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 3")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 4")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 5")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 6")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 7")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 8")
>
> mtext("par(mfrow = c(4, 2)", outer = TRUE, cex = 2, col = "blue")
|
이번에는 par(mfcol = c(4, 2)) 설정된 예를 아래에 들어보았습니다. 위의 par(mfrow = c(4,2))처럼 4개의 row, 2개의 column 창이 만들어진 것은 동일합니다만, 그래프가 그려지는 순서는 다름에 유의하시기 바랍니다. par(mfcol = )은 column-wise 기준이어서 위에서 아래로 열이 다 찰 때까지 먼저 그래프가 그려지고, 그 다음에서야 오른쪽으로 넘어가서 다시 위에서부터 아래로 열을 채워가는 식으로 그래프가 순차적으로 그려지는 식입니다. 그래프를 그리고자 하는 순서, 형태에 대해서 먼저 생각을 해보시고, 원하는 순서/형태에 맞게 mfrow와 mfcol 을 선택하면 되겠습니다.
> ##-- par(mfcol = ) : multiple figures (use COLUMN-wise)
> par(mfcol=c(4, 2), # make frame by 1 row, 2 columns
+ mar=c(4, 3, 3, 1), # inner margin
+ oma=c(0.5, 0.5, 2, 0.5)) # outer margin
>
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 1")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 2")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 3")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 4")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 5")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 6")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 7")
> plot(MPG.highway ~ Weight, Cars93, type="p", main = "plot 8")
>
> mtext("par(mfcol = c(4, 2)", outer = TRUE, cex = 2, col = "blue")
|
layout() 함수를 사용하면 행렬(matrix,mat)로 분할하려는 그래프 영역의 순서(sequence)와 열의 폭과 행의 높이(widths of column, heights of row), 영역 나누기/합치기(divide/combine)를 자유롭게 조절할 수 있으므로 위에서 소개한 par(mfrow = ), par(mfcol = ) 보다 사용자에게 보다 높은 자유도를 제공하므로, 매우 유용하고 강력한 함수라고 하겠습니다.
layout() 함수는 par(mfrow = )나 par(mfcol = ) 함수와는 병행해서 사용할 수 없으므로 그래프 분석을 시작하기 전에 무슨 함수를 사용할 것인지 결정을 하고 하나를 선택해야만 합니다.
layout.show(n)은 현재의 layout에 대한 외곽선을 n 만큼의 그래프 갯수만큼 볼 수 있게 해주는 함수입니다.
아래에 layout()과 layout.show(n) 함수 예를 하나 들어보겠습니다. matrix() arguments 안의 숫자가 그래프가 그려지는 순서인데요, byrow=TRUE 로 했으므로 상단 왼쪽부터 시작해서 지그재그로 4개의 그래프를 그릴 수 있는 영역을 만들어보았습니다. byrow= FALSE 로 지정하면 왼쪽 위에서 왼쪽 아래로, 다시 오른쪽 위에서 오른쪽 아래 방향으로 그래프 생성 순서가 설정됩니다.
> ##-----------------------------------
> ## layout
> ##-----------------------------------
> > # Save default par values
> op <- par(no.readonly = TRUE) >
> # divide the divice into 2 rows and 2 columns
> # allocate figure 1, 2, 3, 4 from upper left to lower right
> layout(matrix(c(1,2,3, 4), 2, 2, byrow = TRUE)) > > # show the current layout
> layout.show(4)
|
layout() 함수를 활용하면 그래프 영역을 합칠 수도 있습니다. 이게 par(mfrow = ) 또는 par(mfcol = ) 대비 꽤 유용한 기능 중의 하나입니다. 2 by 2 로 나눈 영역에서 1행 1열에만 그래프 영역 1개를 남겨놓고, 2행의 1열과 2행의 2열은 합쳐보는 예제를 아래에 들어보겠습니다.
숫자 '0'은 비어있는 그래프 영역이 되겠으며, 동일한 숫자를 행렬(matrix) 안에 나란히 입력하면 그 영역을 합쳐서 제시하라는 뜻입니다. 아래 예에서는 1행2열에 '0'이 입력되었으므로 비어있고, 2행1열과 2행 2열에 나란히 '2'가 기입되었으므로 2행1열과 2행2열이 합쳐져서 1개의 그래프 영역으로 표시가 되었습니다.
> ## divide the device into two rows and two columns
> ## allocate figure 1 the intersection of column 1 and row 1
> ## allocate figure 2 all of row 2
> layout(matrix(c(1,0,2,2), 2, 2, byrow = TRUE))
> > ## show the current layout
> layout.show(2)
|
이해를 돕기위해서 이번에는 1행 1열과 1행 2열을 하나로 합치고, 2행 1열은 비워놓고 2행2열만 남겨놓는 layout을 만들어보는 예제를 아래에 들어보겠습니다.
> ## divide the device into two rows and two columns
> ## allocate figure 1 all of row 1
> ## allocate figure 2 the intersection of column 2 and row 2
>
> layout(matrix(c(1, 1, 0, 2), 2, 2, byrow = TRUE))
>
> ## show the current layout
> layout.show(2)
|
이번에는 10cm 정사각형 모양의 그래프 영역을 생성해보겠습니다. 폭은 widths = lcm( ) 으로, 높이는 heights = lcm( ) 으로 설정을 해주면 되겠습니다.
> ## create single figure of 10cm square
> layout_1 <- layout(matrix(1), widths = lcm(10), heights = lcm(10))
> layout.show(layout_1)
|
이번에는 그래프 생성 순서(sequence)의 위, 아래를 바꾸어 보고, 그래프의 넓이(widths)와 높이(heights)를 서로 다르게 하는 그래프 영역을 만들어보겠습니다. 가운데에 산포도를 그려놓고 상단과 우측에 작은 크기의 히스토그램이나 박스플롯을 병행해서 그릴 때 유용하게 사용할 수 있습니다.
참고로, respect = TRUE 는 가로 넓이와 세로 높이의 비율을 고려해서 그래프 영역을 설정하라는 옵션입니다.
> # divide device into two rows and two columns
> # allocate figure 1 the intersection of column 1 and row 2
> # allocate figure 2 the intersection of column 1 and row 1
> # allocate figure 3 the intersection of column 2 and row 2
> # no plot the intersection of column 2 and row 1
> # widths 8cm and 4cm respectively
> # heights 4cm and 8cm respectively
> # respect relations between widths and heights >
> layout_2 <- layout(matrix(c(2, 0, 1, 3), 2, 2,byrow = TRUE),
+ widths = lcm(c(8, 4)),
+ heights = lcm(c(4, 8)),
+ respect = TRUE)
>
> layout.show(layout_2)
>
> # Reset par to the default values at startup
> par(op)
|
다음번 포스팅에서는 '낮은 수준의 그래프 함수 (Low Level Graphics Functions)'에 대해서 알아보도록 하겠습니다. 앞서의 '높은 수준의 그래프 함수'와 '그래프 모수'에 대해서 예를 들 때 이미 '낮은 수준의 그래프 함수'를 곁들여서 사용하기는 했습니다만, 일목요연하게 한번 더 정리하고 개념을 확실하게 다잡는 다는 의미에서 다음번에 포스팅하도록 하겠습니다.
많은 도움이 되었기를 바랍니다.
이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡' 단추를 꾸욱 눌러주세요.^^