본문 바로가기
e-Logbook

[R] 데이터 손실 없이 ggplot 줌인/줌아웃 하기 (scale, limit 변경)

by Thdnice 2019. 2. 9.
반응형
[R] 데이터 손실 없이 ggplot으로 zoom in/out

[R] 데이터 손실 없이 ggplot으로 zoom in/out

R with ggplot

통계 분석용 언어중 하나인 R 은 그 자체로도 매우 훌륭하지만, 여러 페키지들을 사용하면 그 효용과 활용성이 크게 증가한다. 특히 많이 쓰는 페키지로는 tidyverse, data.table 등등이 있지만, 그 중에서도 시각화에 관련해서 단연 최고라고 할 수 있는 ggplot2 를 절대 빼놓을 수 없을 것이다.

다만 Grammar of Graphics 라는 이름에서부터 느껴지듯, 그림을 그리기 위해서는 ggplot 만의 문법에 어느정도 익숙해져야 하는데 대략적인 사용법은 다음과 같다.

library(ggplot2)
ggplot(data=diamonds, aes(x=carat, y=price, color=clarity)) + geom_point() + theme_bw()

위 예제에서는 내장데이터셋인 diamonds 를 사용하였다. diamonds 에는 다이아몬드의 크기(캐럿), 투명도, 가격등에 대한 정보가 들어있다.

코드에서 보면 마치 블럭을 조립하듯 각 함수가 +로 묶여있는 것을 볼 수 있는데, 위 예제에서는 먼저 ggplot부분에서 어떤 데이터셋을 사용할 것인지, 그리고 geom_point 를 사용해서 Scatter chart로 그리것인지, 그리고 마지막으로 theme_bw 함수를 사용해서 어떤 테마 (예제에서는 black and white) 의 색으로 표현할 것인지를 정의하였다.

따라서 ggplot을 얼마나 잘 사용하는가는 어떤한 블럭들을 +로 잘 연결해서 그림을 그릴 수 있느냐에 달려 있다고 해도 과언이 아니다. 그런데 실제로 어떤 데이터를 시각화해서 보여줄 때에는 특정 영역을 확대하거나 잘라서 보여주는 경우가 많다. 그런경우에는 통상 다음과 같이 xlim 이나 ylim 과 같은 옵션을 사용해서 영역을 지정해주게 된다.

library(ggplot2) 
ggplot(data=diamonds, aes(x=carat, y=price, color=clarity)) + geom_point() + ylim(c(0, 6000)) + xlim(c(0, 3)) + theme_bw()
## Warning: Removed 11551 rows containing missing values (geom_point).

위 예제에서는 x 축을 0부터 3까지, 그리고 y축을 0부터 6000까지 잘라서 보여준 경우이다. 그런데 여기서 눈 여겨 볼 점은 warning 부분인데, 해석해보면 11551개의 데이터가 사라졌다고(missing values) 메시지가 나온다.

즉, xlim 또는 ylim 옵션을 사용하면 화면에서만 사라진 것이 아니라 실제 데이터 자체가 잘려나가는 (clipping) 되어서 나타난다. 만약 이를 방지하고 싶다면 다음의 명령어를 사용하면 된다.

library(ggplot2) 
ggplot(data=diamonds, aes(x=carat, y=price, color=clarity)) + geom_point() + 
  coord_cartesian(xlim=c(0,3), ylim=c(0,6000)) +
  theme_bw()

같은 결과를 얻었지만, 지난번과 같은 경고가 나타나지 않는다. 이 방법은 실제로 데이터는 그대로 두면서 화면에 보이는 영역만 줌인 하는 효과가 있다.

사실 여기까지만 보면 두 방법에 어떤 차이가 있는지 별로 와 닿지 않는다. 그래서 좀 극단적인 다음의 예를 보도록 하자.

x <- 1:10
y <- c( rnorm(3, 0, 1), rnorm(3, 100, 1), rnorm(4, 0, 1))
df <- data.frame( x =x , y=y )
ggplot(data=df, aes(x=x, y=y)) + geom_point() + geom_line() +  theme_bw()

이와 같은 예제에서 x 영역을 3.5에서 6.5까지만 확대할 경우 차이가 극명하게 나타난다.

ggplot(data=df, aes(x=x, y=y)) + geom_point() + geom_line() +  theme_bw() + xlim(3.5, 6.5)
## Warning: Removed 7 rows containing missing values (geom_point).
## Warning: Removed 7 rows containing missing values (geom_path).

이 경우에는 화면 밖에 있는 x=c(1,2,3,7,8,9,10) 의 데이터들이 실제로 제거 되었기 때문에 geom_line 이 4부터 6까지의 데이터만 이어주게 된다.

반면 xlimcoord_cartesian 으로 감싸주게 되면

ggplot(data=df, aes(x=x, y=y)) + geom_point() + geom_line() +  coord_cartesian(xlim=c(3.5, 6.5)) + theme_bw()

이렇게 선이 이어지게 된다.

이러한 차이는 fitting에서도 분명하게 드러나는데, 예를들어 위 데이터를 geom_smooth로 fit할 경우 실제로 xlim 영역안에 들어온 3개의 데이터만을 활용해서 fitting을 진행한다.

ggplot(data=df, aes(x=x, y=y)) + geom_point() + geom_line() + geom_smooth() +theme_bw() + xlim(3.5, 6.5)
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

반면에 coord_cartesian을 사용한 경우에는 전체 데이터를 사용해서 fitting을 진행하기 때문에, 결과가 사뭇 다르게 된다.

ggplot(data=df, aes(x=x, y=y)) + geom_point() + geom_line() + geom_smooth() +theme_bw() + coord_cartesian(xlim=c(3.5, 6.5)) 
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

어느게 더 좋은 방법이라고 말할 수 없는게, 내가 어떤 경우를 의도하느냐에 따라서 데이터를 추려내서 사용하는게 좋을 수 도 있고, 전체 데이터를 사용하고 필요한 부분만 확대해서 보여주는게 좋을 수 도 있다. 따라서 이 2가지 방법 모두 숙지해두는게 여러모로 유용하다.

반응형