본문으로 바로가기



R을 사용한 쿨(Cool)한 그래프 - 4. 여러 그래프를 한번에 그리기 mfrow()

category R Programming/Graphics 2017.05.28 09:39

여러 그래프를 한번에 그리기

오늘은 여러개의 그래프를 한꺼번에 그리는 방법에 대하여 알아보도록 하자. 시작하기 앞서, 준비 단계로 우리가 이제까지 배웠던 그래프 설정을 함수로 저장하도록 하자. 아래와 같이 특정 그래프의 세팅을 해놓으면 매번 그래프를 그리기 위하여 일일이 코드를 써 줄 필요가 없어진다.

emptyPlot <- function(xrange, yrange, ...){
    require("graphics")
    par(bg = "light cyan")  # 팔레트 색깔 하늘색으로 설정
    
    # Generate empty plot
    plot(# x, y 그래프 범위 설정
        c(0,0),c(1,1),
        # xlab = "",        # x 축 제목
        # ylab = "",        # y 축 제목 생략
        xlim = c(xrange[1], xrange[2]),
        ylim = c(yrange[1], yrange[2]),
        type = 'n',         # '표시 안함'으로 설정
        las = 1,
        ...
    )
    
    # 배경 노란색으로 설정
    loc <- par("usr")
    rect(loc[1], loc[3], loc[2], loc[4],
         col = "lemonchiffon")
    
    # 참조선 작업(이전 포스팅 참조)
    abline( v = axisTicks(loc[1:2], log = FALSE),
            h = axisTicks(loc[3:4], log = FALSE),
            col = "black", lty=3)
    abline( v = 0, lty = 1)
    abline( h = 0, lty = 1)
    
    # 배경색 리셋
    par(bg = "white")
}

다음과 같이 정의한 emptyPolot() 함수를 사용하여 앞 시간에 배웠던 Sin함수를 그려보면, 코드가 많이 줄었다는 것을 알 수 있다. emptyPlot()을 정의할 때 을 사용하였기 때문에, plot() 함수의 여러 설정들을 나중에 emptyPolt() 함수를 사용할 때 정의해 줄 수 있게 되었다는 것을 유의해서 보자(나중에 자신의 함수를 정의해서 사용할 때 아주 유용하다).

x <- seq(0,2*pi, length.out = 100)
y <- sin(x)
emptyPlot(c(0,2*pi), c(-1, 1),
          main = "Sin x",
          xlab = "x", ylab ="Sin(x)")
points(x,y, type = 'l', col = "Red")

자, 이제 오늘 강의를 위한 준비는 끝났다. 여러개의 그래프를 그리기 위해 사용되는 방법은 크게 두 가지로서, mfrow()를 이용하는 방법과 layout()를 이용하는 방법이 있다. 이번 포스팅에서는 mfrow()를 이용하는 방법에 대하여 설명하도록 하겠다. 만약 우리가 Sin()Cos()의 그래프를 위 아래로 비교해서 그리고 싶다면, 한 개의 팔래트를 아래와 같이 구역 1과 구역 2와 같이 두 공간으로 나줘주면 된다.

\[ \left(\begin{array}{c} \text{구역 1}\\ \text{구역 2} \end{array}\right) \]

팔레트 전체를 하나의 행렬로 생각하면 팔레트를 2행 1열의 구역으로 나눠준다고 생각하면 된다. 이것을 R코드로 표현하면 다음과 같다. 참고로 나뉘어진 팔레트를 다시 원래대로 돌리고 싶은 경우에는 par(mfrow=c(1,1))이나 dev.off()를 사용하여 리셋해주면 된다.

# 데이터 준비
x <- seq(0,2*pi, length.out = 100)
y <- sin(x)
z <- cos(x)

# 팔레트 구역 나누기 1행 2열
par(mfrow = c(2,1))

# Plot 1
emptyPlot(c(0, 2*pi), c(-1,1),
          main = "구역1", xaxt = 'n',
          xlab = "x", ylab = "Sin(x)")
points(x,y, type = 'l', col = "Red")

# Plot 2
emptyPlot(c(0, 2*pi), c(-1,1),
          main = "구역2",
          xlab = "x", ylab = "Cos(x)")
points(x,z, type = 'l', col = "Blue")

결과물을 살펴보면 예상했던 것처럼 그래프가 위아래로 나란히 출력되어 있는 것을 알 수 있다. 하지만, 두 개의 그래프가 너무 떨어져 있다는 느낌이 든다. 사실 그래프 두 개를 붙여서 그리는데에는 두 그래프를 놓고 비교하기 쉽게 하려는 의도가 있기에 두 그래프 사이의 여백(margin)을 조정해 줄 필요가 있다. 이것을 가능하게 해주는 기능이 그래프 패라미터 함수, par() - 예전 포스팅에서 팔레트 색깔을 지정해줄때 사용했던 함수,에 들어있는 mar() 함수이다. ?par 명령어를 사용하여 par함수의 mar에 대한 설명을 보면 다음과 같다.

mar
A numerical vector of the form c(bottom, left, top, right) which gives the number of lines of margin to be specified on the four sides of the plot. The default is c(5, 4, 4, 2) + 0.1.

즉, 그래프와 팔래트 사이의 거리를 4개의 원소로 가지는 벡터로 조정할 수 있다는 이야기인데, 필자는 처음 왜 저런 순서로 정의를 했는지에 대해 의문을 가졌었다. 위, 아래, 왼쪽, 오른쪽이 더 편해 보이는데 말이다. 설명서를 참고해보니, 아래 6시 방향을 기준으로 시계방향으로 정의를 한 것 같다. 아래의 그림을 보면 좀 더 이해가 쉬울 것이다.

따라서, 앞에서 사용했던 코드의 여백을 조정하는 부분을 추가해서 그려보자. 위에 그려질 Sin() 함수 그래프의 여백은 제목을 나타내기 위한 위쪽 여백 2, 아래 그래프와의 여백 2를 부여했다. 아래에 그려질 Cos() 함수의 경우에는 제목이 필요없으므로 위쪽 여백을 0으로 설정하고, 반대로 아래쪽 여백을 4을 부여하여 x축 레이블이 보여지도록 설정하였다. 전체 R코드와 결과는 아래와 같다.

# 데이터 준비
x <- seq(0,2*pi, length.out = 100)
y <- sin(x)
z <- cos(x)

# 팔레트 구역 나누기 1행 2열
par(mfrow = c(2,1))

# Plot 1
# margin 아래, 왼쪽, 위, 오른쪽
par(mar = c(2,4,2,2))
emptyPlot(c(0, 2*pi), c(-1,1),
          main = "Sin(x) & Cos(x) graph", xaxt = 'n',
          xlab = "", ylab = "Sin(x)")
points(x,y, type = 'l', col = "Red")

# Plot 2
par(mar = c(4,4,0,2))
emptyPlot(c(0, 2*pi), c(-1,1),
          main = "",
          xlab = "x values", ylab = "Cos(x)")
points(x,z, type = 'l', col = "Blue")

다음 시간에는 좀 더 자유롭게 패널을 나눌 수 있는 layout() 함수를 이용하여 여러개의 그래프를 그리는 방법에 대하여 알아보겠다.

도움이 되셨다면, 로그인 없이 누를수 있는 아래에 공감버튼을 눌러주세요. 필자에게 큰 힘이 됩니다. :D


SHARE TO



티스토리 툴바