프로젝트 과제, 세부 업무 별로 시작 시점과 끝 시점을 선으로 그어서 한 눈에 일정 관리를 할 수 있도록 도와주는 시각화 기법으로 간트 차트(Gantt Chart)를 많이 사용합니다. 


간트 차트가 일정 관리 측면에서는 매우 강력한 시각화 도구이다 보니 간트 차트를 쉽고 빠르게 그릴 수 있도록 도와주는 '뉴간트메이커 간트 차트', '차트 스쿨 2.0', 'GanttProject', 'Online Gantt Chart' 등의 전문 소프트웨어가 있습니다. 


R을 가지고도 간트 차트를 그릴 수 있는데요, 이번 포스팅에서는 R의 timevis 패키지를 사용해서 간트 차트를 그리는 방법을 알아보겠습니다. 


R로 간트 차트를 그리려고 반나절 이상을 골머리를 앓다가 timevis 패키지를 발견하고서 얼마나 반가웠는지 모릅니다. 그리고 timevis 패키지를 사용해보니 제공하는 기능이 매우 놀라웠습니다. 들인 노력 대비 산출물이 매우 세련되 보이거든요. interactive 기능도 제공합니다. ^^b  timevis 패키지는 vis.js 의 timeline module 과 htmlwidgets R package 를 근간으로 해서 만들어졌다고 하는걸 보니 java script 기반의 패키지를 가지고 R 바인딩해놓은 같습니다. 


timevis 패키지는 Dean Attali 라는 분이 오픈 소스로 개발했는데요, R-Shiny founder라고 자기소개에 나와있네요. 요즘 탐색적 데이터 분석(Exploratory Data Analysis)하는데 R-Shiny 사용해보면서 감탄하고 있는데요, R-Shiny app에 timevis 로 그린 간트차트도 추가해서 이쁘게 app하나 만들었더니 간지 나더라구요. Dean Attali 개발자님께 이래저래 고마운 마음 전합니다. ^^b


아래 포스팅은 Deam Attali의 Git-Hub(https://github.com/daattali/timevis) 페이지와 R ?timevis 도움말의 예제 코드를 거의 수정없이 인용해서 작성하였구요, 그래프의 화면 캡쳐와 동영상을 추가해서 처음 사용하시는 분의 이해를 조금 더 돕는다는 취지로 작성을 해보았습니다. 



1. timevis 패키지 설치 및 로딩



##---------------------------------

## gantt chart by timevis package

##---------------------------------


# reference : https://github.com/daattali/timevis


# install timevis package

install.packages("timevis")

 




2. 날짜 데이터 입력 없는 상태에서 timeline 형태 살펴보기 


아래 timeline의 가운데 빨간 선은 시스템 날짜(Sys.Date) 입니다. 



# minimum view of timeline without any data at system time

library(timevis)

timevis()

 






3. 특정 날짜(Item), 혹은 기간(Range) 데이터를 입력한 간트 차트 (Gantt Chart) 그리기


timevis 패키지에서 사용하는 데이터셋이 데이터프레임(DataFrame)이라는 점이 원천 데이터를 거의 손볼 필요없이 그대로 사용할 수 있어서 저는 매우 좋더군요.  아래의 R script 처럼 'id', 'content', 'start', 'end'라는 칼럼이 데이터프레임에 포함되어 있으면 됩니다. 


  • id : 인덱싱(indexing) 할 때 사용
  • content : 간트 차트에 포함될 내용
  • start : 시작 시간 (년-월-일, 혹은 년-월-일 시간:분:초 포맷)
  • end : 끝 시간 (년-월-일, 혹은 년-월-일 시간:분:초 포맷)


start은 반드시 날짜, 혹은 날짜&시간 데이터가 들어가야만 에러가 안나구요, end 칼럼에는 NA 결측값으로 비워두어도 상관없습니다. end 칼럼에도 일시 데이터가 들어가면 start ~ end 의 기간(range)의 timeline 이 선으로 길게 그려집니다. 



# adding data to timevis() by DataFrame

data <- data.frame(

  id      = c(1:4),

  content = c("Item_First"  , "Item_Second"  ,"Ranged_First", "Ranged_Second"),

  start   = c("2017-05-26", "2017-05-27 01:30:00", "2017-05-27 05:00:00", "2017-05-30"),

  end     = c(NA          , NA                   , "2017-05-28 15:00:00", "2017-05-31 03:10:00")

)


# view of Gantt chart

timevis(data)

 






4. 데이터프레임의 각 칼럼 데이터 형태


input으로 사용되는 DataFrame의 각 칼럼의 데이터 행태를 살펴보면 id는 정수형(integer), content, start, end는 요인형(factor) 입니다.  혹시 데이터프레임 만들어서 timevis() 함수 적용했는데 그래프가 안그려지고 에러가 나면 content, start, end 칼럼의 데이터 형태가 요인형(factor)인지 확인해보시기 바라며, 혹시 문자형(character)으로 되어 있으면 as.factor() 를 사용해서 요인형으로 변환 후에 timevis() 를 다시 적용해보시기 바랍니다. 



> # checking data type

> sapply(data, class)

       id      content      start        end 

"integer"  "factor"  "factor"  "factor"

 




5. Zoom-in, Zoom-out, 좌-우 이동하는 동적 시각화


우측 상단에 있는 '+' 단추를 누르면 'Zoom-in'이 되어 더 짧은 기간으로 현미경의 눈으로 심화해서 간트 차트를 그려줍니다 (아래 그림 예시).  반대로 '-' 단추를 누르면 'Zoom-out'이 되어 높은 하늘 위의 새의 눈으로 더 넓은 기간의 간트 차트를 보여줍니다. 


 





커서로 timeline 을 클릭한 후에 좌, 우로 끌고 가면 간트 차트가 동적으로 움직이며, 마우스 휠을 사용해서도 Zoom-in, Zoom-out 을 할 수가 있습니다.  동적으로 움직이는 신기한(?) 그래프를 단 한 줄의 R script (즉, timevis(data) 로 끝) 로 만든 것입니다.  말로 설명하려니 감흥이 덜할 것 같은데요, 아래 동영상 참고하세요. 





6. Zoom 단추 숨기기, 편집 기능 설정, timeline 높이 설정


  • showZoom = FALSE   : 우측 상단의 Zoom 단추 숨기기  ( <= 이거 없어도 마우스 휠 사용하면 됨)
  • options = list(editable = TRUE)  :  TRUE 이면 timeline bar를 커서로 선택했을 때 색이 바뀌며, 'X' 표시를 누르면 간트 차트에서 사라짐 
  • options = list(height = "300px")  : timeline 높이를 하드 코딩으로 설정 ( <= 이거 굳이 하드코딩 안해줘도 알아서 유동적으로 높이 잘 조정해 줌) 


# hide the zoom buttons, options for editable, height

timevis(data, 

            showZoom = FALSE, 

            options = list(editable = TRUE, 

                                  height = "300px"))


 




7. %>% chain operator, 일정 추가(add Item), 디폴트 일정 선택(set Selected Item)


  • timevis() %>% : chain operator  (dplyr 패키지 사용해본 분이라면 익숙하실 듯)
  • setItems(data.frame(id, content, start, end)) : id, content, start, end(optional) 로 이루어진 원본 데이터셋
  • addItem(list(id, content, start, end)) : 개별 일정을 추가하고 싶을 때 사용
  • setSelection("1") : 간트 차트가 화면에 떴을 때 처음 선택이 되게 하고 싶은 id 를 지정 (아래 예에서는 "1"번의 "one" item 이 색깔이 바뀌어 있고, editable = TRUE 로 설정했으므로 'X' 표시가 같이 나타남)


# %>% operator, set editable Options, add Item, set Selected Item

timevis() %>%

  setItems(data.frame(

    id = 1:2,

    content = c("one", "two"),

    start = c("2017-05-28", "2017-05-30")

  )) %>%

  setOptions(list(editable = TRUE)) %>%

  addItem(list(id = 3, content = "three", start = "2017-05-29")) %>%

  setSelection("1") 





8. 그룹(group)으로 묶어서 간트 차트 구성하기


업무의 특성(예: 컨설팅, 개발), 프로젝트 단계(예 : Phase 1, Phase 2), 조직(예: 설계팀, 개발팀, 지원팀) 등 특정 기준에 따라서 Item 들을 그룹으로 묶어서 간트 차트를 그리고 싶을 때가 있습니다.  이 기능을 잘 사용하면 간트 차트를 좀더 구조화해서 보여줄 수 있으므로 일목요연하게 시각화하는데 매우 유용합니다. 



# using the groups feature to group together multiple items into different buckets

timevis(

  data = data.frame(

    start = c(Sys.Date(), Sys.Date(), Sys.Date() + 1, Sys.Date() + 2),

    content = c("one", "two", "three", "four"), 

    group = c(1, 2, 1, 2)),

  groups = data.frame(id = 1:2, content = c("Group_1", "Group_2"))

)

 




9. timevis() 간트 차트를 RShiny 에 연동


RShiny 에도 timevis() 패키지를 사용해서 간트 차트, timeline을 삽입할 수 있습니다.  RShiny 문법에 대해서는 이 포스팅에서 설명하자면 너무 길어지게 되므로 생략하겠구요, 동적 문서(Dynamic Document) 카테고리에서 별도로 나중에 포스팅하겠습니다. 



# RShiny


library(shiny)


data <- data.frame(

  id = 1:3,

  start = c("2015-04-04", "2015-04-05 11:00:00", "2015-04-06 15:00:00"),

  end = c("2015-04-08", NA, NA),

  content = c("<h2>Vacation!!!</h2>", "Acupuncture", "Massage"),

  style = c("color: red;", NA, NA)

)


ui <- fluidPage(

  timevisOutput("appts"),

  div("Selected items:", textOutput("selected", inline = TRUE)),

  div("Visible window:", textOutput("window", inline = TRUE)),

  tableOutput("table")

)


server <- function(input, output) {

  output$appts <- renderTimevis(

    timevis(

      data,

      options = list(editable = TRUE, multiselect = TRUE, align = "center")

    )

  )

  

  output$selected <- renderText(

    paste(input$appts_selected, collapse = " ")

  )

  

  output$window <- renderText(

    paste(input$appts_window[1], "to", input$appts_window[2])

  )

  

  output$table <- renderTable(

    input$appts_data

  )

}


shinyApp(ui, server)


 



[Reference] https://github.com/daattali/timevis


많은 도움 되었기를 바랍니다. 


이번 포스팅이 도움이 되셨다면 아래의 '공감~'를 꾸욱 눌러주세요. ^^



Posted by R Friend R_Friend

댓글을 달아 주세요