inst/KorText/app.R

### R Shiny 구현 (20.3.10)

# install libraries
libraries = c("shiny",
              "shinyFiles", # 디렉토리 지정
              "shinycssloaders", # 페이지 로딩효과
              "shinythemes" # App 테마 설정
              ) 
libraries = c(libraries, c("shiny","RKOMORAN","tm","stringr","tidyverse","dplyr","tidytext","tidyr"))
install.packages(setdiff(libraries, installed.packages()))

# import libraries
library(shiny)
library(shinyFiles) 
library(shinycssloaders) 
library(shinythemes) 

# set environment
source("global.R", encoding="UTF-8")

# Part 1. UI
ui = fluidPage(
  
  # fluidPage = 윈도우 크기에 따라 폭/높이 등 자동으로 조절됨
  
  # navbarPage = 상단에 navigation bar 생성
  navbarPage(
    
    # 테마 설정
    theme=shinytheme("flatly"),
    
    # Shiny App 제목 지정
    title="DEMO",

    # tabPanel 함수로 여러 개 탭을 생성할 수 있음
    tabPanel(
      
      # "텍스트분석"이라는 탭 만들어 담을 것
      title="텍스트분석",
      
      # 구성 A. sidebarPanel
      # : 왼쪽 패널에서 3단계로 옵션 지정
      sidebarPanel(
        
        # width 옵션으로 폭 조정
        width=3,
        
        # (1) 디렉토리 지정
        
        # html 문법을 이용하면 간편히 텍스트 입력 가능
        # h+"숫자" 형식; 숫자가 커질수록 글씨크기는 줄어듦
        h4("1. 폴더 지정하기",),
        h5("분석할 텍스트 파일(.txt)이 위치한 폴더를 지정해주세요."),
        
        ## shinyDirButton()
        shinyDirButton(id="directory",
                       label="Set Directory",
                       title="1. 폴더 지정하기"), # 팝업창 제목
        # Shiny App의 각 구성요소는 id와 label로 이루어져 있음
        # id: 해당 요소를 불러오고 액션을 취하기 위해서는 id로 호출
        # label: 해당 요소가 display되는 텍스트 내용
        # 즉 실제로 보여지는 것은 label, 코딩에 쓰이는 것은 id
        
        # br() = 줄바꿈
        br(),
        br(),
        
        # (2) 문학/정보전달 유형 선택
        h4("2. 텍스트 유형 선택하기"),
        
        ## radioButtons()
        radioButtons(inputId="filetype",
                     label="File type:",
                     choices=c("문학텍스트"="nar",
                               "정보전달텍스트"="info")),
        # 같은 원리로 "nar"는 id, "문학텍스트"는 라벨
        
        # 폴더 및 유형선택이 끝났다면 버튼을 눌러 분석
        ## actionButton()
        actionButton(inputId="do",
                     label="Submit",
                     class="btn-warning"),
        br(),
        br(),
        
        # (3) 다운로드
        h4("3. 분석결과 다운로드"),
        h5("결과를 .csv 파일로 저장합니다."),
        downloadButton(outputId="downloadData",
                       label="Download")
        # output 파트와 연결되므로 outputId
        ),
      
      # 구성 B. mainPanel
      # : 오른쪽 패널에서 분석 결과 도시
      mainPanel(
        # 윗줄에는 폴더 위치를 나타냄
        fluidRow(column(width=6,
                        tags$b(textOutput("text")))
                 ),
        # hr() = 가로줄
        hr(),
        # 아랫줄에는 분석 결과를 테이블로 나타냄
        # withSpinner() 함수로 로딩 효과 줄 수 있음
        fluidRow(column(width=12,
                        dataTableOutput("table") %>%
                          withSpinner(color="grey", type=8)))

        )
    ),
    
    # 다른 탭도 생성 가능
    tabPanel(title="Tab 1"),
    tabPanel(title="Tab 2")
  )
)

# Part 2. Server
server = function(input, output, session) {
  
  # (1) 디렉토리 지정
  # 현재 컴퓨터에서 가능한 디렉토리 불러오기(C:, D: 등)
  volumes <- getVolumes()
  ## shinyDirChoose()
  # : id=directory인 UI의 버튼과 연결됨
  shinyDirChoose(input=input,
                 id="directory",
                 roots=volumes,
                 session=session,
                 filetypes=c("txt")) # .txt 파일만 포함
  
  # reactive() = input에 종속적
  # input$directory 지정이 끝나면 directory path를 저장
  # 이 경우 함수 형식으로 작성 및 사용해야 함에 주의
  path <- reactive({
    return(parseDirPath(roots=volumes,
                        selection=input$directory))
  })
  
  # (2) 문학/정보전달 유형 선택
  # 이후 데이터 분석 과정
  
  # eventReactive() = input의 특정한 action에 종속적
  # 앞서 id=do인 분석하기 버튼이 눌리면 동작 시작
  result <- eventReactive(input$do, {
    # id=filetype인 텍스트 유형에 따라
    switch(input$filetype,
           
           # nar(문학)인 경우 func_nar
           "nar"=tryCatch({
             func_nar(path(), user_dic_N, lexicon)},
             error = function(e) {NULL}),
           
           # info(정보전달)인 경우 func_info
           "info"=tryCatch({
             func_info(path(), user_dic_I, lexicon)},
             error = function(e) {NULL}))

  })
  # 참고. 폴더위치를 인자로 받는 VCorpus 함수가 에러에 취약
  # tryCatch 함수를 이용해 에러 예외처리함.
  # 폴더 선택이 끝나지 않았거나, 알맞은 폴더를 선택하지 않은 경우
  # result=NULL, 즉 빈 값을 부여함
  
  ## 아래는 main panel에 들어갈 두 가지 Output
  
  # Output 1: Text (폴더 위치)
  output$text <- renderText({
    paste("[폴더 위치]", path())
  })
  
  # Output 2: Table (분석 결과)
  output$table <- renderDataTable({
    result()
  })
  
  # (3) 다운로드
  output$downloadData <- downloadHandler(
    filename = function() {
      # id=filetype인 텍스트 유형에 따라 다른 이름 부여
      typename <- switch(input$filetype,
                    "nar" = "narrative_text_analysis_result",
                    "info" = "informational_text_analysis_result")
      # .csv 파일로 설정
      paste0(typename, ".csv")
    },
    content = function(file) {
      # 설정한 이름으로 저장하기
      write.csv(result(), file, row.names=FALSE)
    }
  )
}

# Part 3. Run App
shinyApp(ui, server)
rinseo/KorText documentation built on March 26, 2020, 12:10 a.m.