본문 바로가기

[R] for 문으로 그래프 생성: ggplot2, for, assign, paste

R Programming/Data Visualization by Mandarim_ 2022. 8. 7.

앞 장에서 여러 그래프 한 번에 타나내는 법을 다루었다.

그래프를 하나씩 g1, g2로 정의하여 gird.arrange() 함수를 이용하여 나타내면 된다.

하지만, 나타내려는 그래프 수가 10개를 넘어간다면, 그래프를 하나 하나 정의하려면 힘들 것이다.

 

그래서 이번 글에서는 For문을 이용해서 자동화된 방식의 코드 구현 을 하고자 한다.


<앞 장 링크>

 

여러 그래프 한 번에 나타내기: ggplot2, gridExtra

hyemstat.tistory.com

 

R코드 - 기본

gird.arrange()를 사용하려면, 각각의 그래프를 하나의 오브젝트로 저장해두어야 한다.

이를 위해, paste0()assign()을 활용하고자 한다. 둘은 R의 기본함수로 따로 패키지를 설치할 필요는 없다.

 

 - paste()와 paste0()

 : Concatenate vectors after converting to character.

paste (..., sep = " ", collapse = NULL, recycle0 = FALSE) paste0(..., collapse = NULL, recycle0 = FALSE)
paste0(..., collapse = NULL, recycle0 = FALSE)

원하는 캐릭터 문자열 (" " 혹은 ' ' 에 담긴)을 파라미터로 받고, 받은 파라미터를 모두 연결시킨 형태로 반환한다.

paste0는 paste0의 sep = "" 인 특수한 형태로, 문자열 사이에 구분자를 놓지 않고 연결시켜준다.

 

 - assign() 함수

 : Assign a value to a name in an environment.

assign(x, value, pos = -1, envir = as.environment(pos), inherits = FALSE, immediate = TRUE)

 변수이름 x (문자열)에 value를 저장시켜주는 함수이다.

 

 - 이해를 위한 코드

for (i in 1:5){
  o_name <- paste0("object", i)
  assign(o_name, i)
}

다음과 같은 코드는 object1, object2, ..., object5에는 각각 1,2,3,4,5의 값을 갖도록 정의한 것이다.

 

정의된 객체 확인
Rstudio에서 정의된 변수를 확인하시면 좀 더 이해가 쉽습니다.

 


 

R코드 - ggplot2에 응용하기

ggplot2의 경우 세부적입 옵션이나 함수 구조가 복잡해보이기 때문에, 어렵지만 위에서 소개한 코드와 같은 구조를 갖는다.

각 그림은 setting별로 그려질 것이기 때문에 setting에 대한 for문 구조 를 작성한다.

 

if () 를 통해 필요한 부분에 필요한 옵션을 설정 할 수 있다.

 

글쓴이의 경우엔 기본으로 모든 그래프는 legend.position = 'none', xlab(""), ylab("") 으로 설정을 맞춰서 그려둔 뒤,

뒤의 IF를 통해 필요한 그래프에만 필요한 옵션을 추가하도록 작성한다.

 

그리고 scale_x_continuous의 break옵션을 설정하지 않으면,

실제 데이터엔 200, 400, 800 값 있지만, 200, 400, 600, 800 과 같이 숫자가 표시되므로 혼동을 줄 수 있다.

 

(shared_legend()함수와 grid.arrange()에 쓰이는 옵션들은 이 전 글에서 자세히 설명해 두었습니다)

(코드에 사용된 자료는 예전에 만들었던 실험결과이며, 주요 변수나 이름은 바꾸어서 사용했습니다.)

 

theme_set(theme_bw())
for (s in 1:8) {
  tmp <- SIM_Results[SIM_Results$setting==s, ]

  g <- ggplot(data=tmp, aes(x=nn, y=mean_ACC, color=Criteria)) + geom_line()+ 
    scale_x_continuous(breaks=c(200, 400, 800) ) + scale_y_continuous(limit=c(0,1))+
    theme(legend.position ='none') +
    xlab("") + ylab("") +  labs(title=paste0("scenario ", s))
  
  
  if (s %in% c(1, 5)) g <- g+ylab("Accuracy")
  if (s==1) g2 <- g+theme(legend.position='bottom')  
  
  assign(paste0('Accuracy_', s), g)
}

extract_legend <- function(my_ggp) {
  step1 <- ggplot_gtable(ggplot_build(my_ggp))
  step2 <- which(sapply(step1$grobs, function(x) x$name) == "guide-box")
  step3 <- step1$grobs[[step2]]
  return(step3)
}

shared_legend <- extract_legend(g2)
g_1_4 <- grid.arrange(Accuracy_1, Accuracy_2, Accuracy_3, Accuracy_4, nrow=1, ncol=4)
g_5_8 <- grid.arrange(Accuracy_5, Accuracy_6, Accuracy_7, Accuracy_8, nrow=1, ncol=4, bottom="Sample Size (n)")

grid.arrange(g_1_4, g_5_8, nrow=3, heights = c(5, 6, 1), shared_legend)

 

bottom = "Sample Siza (n)"을 g_5_8는 가장 마지막에 추가할 수 있지만, legend보다 아래에 y축이 위치하게 된다.

 

완성된 그림은 다음과 같다.

최종그림
위의 코드로 작성된 그림입니다.

반응형