Chapter 22 shinyapps

마크 다운에 이어서, R을 이용하여 결과물을 보여줄 때 많이 사용하는 프로그램은 샤이니 앱입니다. 샤이니 앱은 자체 tutorial이 너무 잘 되어 있어서 이를 보고 따라하는 것이 가장 도움이 될 것 같네요. 이번 시간에는 구조를 설명하는 것을 하고, 전반적인 것은 shinyapp 페이지를 이용하는 것으로 하겠습니다. 여기서는 샤이니앱으로 이러한 정도를 할 수 있다는 것을 알아 두시면 되겠습니다. 웹을 구동하려면, 서버와 DB를 이용하는 부분이 있어서 Dspub-Project에서 다루게 됩니다.

22.1 설치

설치는 shiny 페키지를 설치하는 것입니다.

#install.packages('shiny')
library(shiny)

22.2 예제

아래의 예제를 실행해 보세요

runExample("01_hello")

22.3 예제 1 만들기

22.3.1 구조

구조는 ui, sever로 구성됩니다. ui는 웹이 보여줄 부분, server는 그것이 작동하는 부분입니다. 아래와 같은 구조 입니다 .

library(shiny)
ui     = fluidPage()
server = function(input, output)
shinyApp(ui = ui, server = server)

이에 sidebarLayout을 그 안에 sidebarPanel과 mainPanel을 만듭니다. 이제 구조는 완성이 되었습니다.

library(shiny)
ui     = fluidPage(
   titlePanel("안녕하세요! 윤진하입니다."), 
   sidebarLayout(
     sidebarPanel(), 
     mainPanel()
   ) 
   
)
server = function(input, output){}
shinyApp(ui = ui, server = server)

22.3.2 input, output

input과 ouput을 만듭니다. input을 ui를 통해 받고 이를 server에 옮긴 후 ouput을 만들고, 다시 이를 ui에 output으로 보여주는 방식입니다. 우선 ui에 input을 만들겠습니다. 그래서 그래프를 그려 보도록 하겠습니다.

library(shiny)
ui     <- fluidPage(
  titlePanel("안녕하세요!"),   # 여러분 이름 넣으세요
  sidebarLayout(
    sidebarPanel (
      sliderInput( inputId = "bins", # server input$bins
                   label = "Number of bins", 
                   min =1, max =50, value =30
                   )
    ), 
    mainPanel(
      plotOutput(outputId = "disPlot")
    )
  )
)
server <- function(input, output){
  output$disPlot <- renderPlot({
    hist(faithful$waiting, breaks = input$bins)
  })
}
shinyApp(ui = ui, server = server)

22.3.3 과제

sliderInput의 내용을 수정하여 동영상과 같은 app을 만드세요.

22.4 지도앱 만들기

이번에는 지도 앱을 만들어 보겠습니다. 최종적으로 2단계에 걸쳐 실습을 하겠습니다. 첫번째 실습은 지도를 띄우고 원하는 지역에 마크를 넣는 것입니다. 이후 원하는 지역을 클릭하면 원하는 정보가 뜨게 하는 앱을 만드는 것입니다.


최종적인 모습은 https://sehnr.org/apps/indmap/ 와 같습니다.
산단지역지도

ui, server, global, datastep의 파일을 아래와 같습니다. 이를 이용해서 영상을 보고 따라해 보세요.

datastep

# ui, server ,global, datastep
# ui {heaser, seidebar, body(tab)}
# server output
# global (data, packages, sourcefile.)

url1 = "https://dspubs.org/webapps/forum/open_data/priority.rds"
url2 = "https://dspubs.org/webapps/forum/open_data/styles.css"
url3 = "https://dspubs.org/webapps/forum/open_data/gomap.js"
url4 = "https://dspubs.org/webapps/forum/open_data/Icon.R"
#url5 = "https://dspubs.org/webapps/forum/open_data/priority.rds"
download.file(url1, "db/priority.rds")
download.file(url2, "source/styles.css")
download.file(url3, "source/gomap.js")
download.file(url4, "source/Icon.R")

global

if(!require("shiny")) install.packages('shiny')
if(!require("shinydashboard")) install.packages('shinydashboard')
if(!require("shinyjs")) install.packages('shinyjs')
if(!require("sodium")) install.packages('sodium')
if(!require("data.table")) install.packages('data.table')
if(!require('leaflet')) install.packages('leaflet', dependencies =TRUE)
if(!require('tidyverse')) install.packages('tidyverse', dependencies =TRUE)
if(!require('scales')) install.packages('scales', dependencies =TRUE)
if(!require('lattice')) install.packages('lattice', dependencies =TRUE)
if(!require('leafpop')) install.packages('leafpop', dependencies =TRUE)

priority = readRDS("db/priority.rds")
source("source/Icon.R")

ui

ui = dashboardPage(
  dashboardHeader(title = "나는 출장갈꺼야"), 
  dashboardSidebar(
    sidebarMenu(
      menuItem("Map", tabName = "Map", icon=icon("dashboard")), 
      menuItem("Table", tabName = "Table", icon=icon("th"))
    )
  ), 
  dashboardBody(
    tabItems(
      tabItem(tabName = "Map", 
              div(class="outer", 
                  tags$head(
                    includeCSS("source/styles.css"),
                    includeScript("source/gomap.js"), 
                    tags$head(name="viewport", 
                              content="width=device-width, initial-scale=1.0")), 
                  leafletOutput("map", width="100%", height="100%")
              )
              
              
      ), 
      tabItem(tabName = "Table","너는 표가 될꺼야.")
    )
  )
)

server

server = function(input, output, session){
  
  output$map <-renderLeaflet({
    leaflet() %>%
      addProviderTiles("Stamen.Terrain", group = "Terrain") %>%
      addProviderTiles("CartoDB.Positron", group="Positron") %>%
      addProviderTiles("Esri.WorldImagery", group="Worldimage") %>%
      addTiles(group ='default') %>%
      setView(lng=127.5, lat=36.5, zoom = 7.5)
    
  })
  #map options
  leafletProxy("map", data=priority) %>%
    addAwesomeMarkers(~long_ind, ~lat_ind, 
                      icon = indIcon, 
                      layerId = ~ind_code, 
                      clusterId = ~rank,
                      clusterOptions = markerClusterOptions()) %>%
    addCircles(~long_ind, ~lat_ind, radius= ~rad_ind, 
               layerId = ~ind_code, fillOpacity=0.5, stroke = FALSE) %>%
    addLayersControl(
      baseGroups = c("Positron","Worldimage", "Terrain", "default")
      
    )
  
}