Technical

Creating a Simple SHINY App

R is powerful Language to implement algorithms for Data Sciences, Machine Learning, Artificial Intelligence, etc.

One need for every Develop is to develop a Data Product around the algorithm developed so that public in general could use the algorithm and benefit from it.

One easy and powerful way to develop Web Application in R is to develop SHINY Apps.

SHINY Apps can be very complex and create very complex Web Applications. However, one needs to make a start with a simple application. Once one understand the basics, developing any application becomes possible.

This video goes through the nuances of creating a simple SHINY App.

Code

app.utf8.md
#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

#################   INSTALL PACKAGES IF REQUIRED   #################
v_required_packages <- c("shiny", "english", "shinythemes")

for (v_package in v_required_packages) {
    if(v_package %in% rownames(installed.packages()) == FALSE) 
    {
        install.packages(v_package, dependencies=TRUE)
    }
}

#################   LOAD THE REQUIRED PACKAGES   #################
library(shiny)
library(shinythemes)
library(english)

#################   CONVERT NUMBER TO WORDS IN INDIAN STYLE ######
numbers2wordsIndia <- function(x){
    helper <- function(x){
        if (x < 0) { return(paste(x, "is negative!")) }
        
        digits <- rev(strsplit(as.character(x), "")[[1]])
        nDigits <- length(digits)
        if (nDigits == 1) as.vector(ones[digits])
        else if (nDigits == 2)
            convert2DigitNumbers(x)
        else if (nDigits == 3) 
            convert3DigitNumbers(x)
        else if (nDigits == 4 || nDigits == 5) 
            convertThousands(x)
        else if (nDigits == 6 || nDigits == 7) 
            convertLakhs(x)
        else if (nDigits == 8 || nDigits == 9) 
            convertCrores(x)
        else
            trim(paste(numbers2wordsIndia(floor(x/10000000)), "crore", convertCrores(x %% 10000000)))
    }
    
    convert2DigitNumbers <- function(x) {
        if ( x > 0 && x <= 99 ) {
            digits2DigitNumber <- rev(strsplit(as.character(x), "")[[1]])
            if (x <= 9) as.vector(ones[digits2DigitNumber])
            else if (x <= 19) as.vector(teens[digits2DigitNumber[1]])
            else {
                if (digits2DigitNumber[1][1] == "0") {
                    trim(paste(tens[digits2DigitNumber[2]]))
                }
                else {
                    trim(paste(tens[digits2DigitNumber[2]], as.vector(ones[digits2DigitNumber[1]])))
                }
            } 
        }
    } 
    
    convert3DigitNumbers <- function(x) {
        if ( x > 0 && x <= 999 ) {
            if ( x < 100 ) convert2DigitNumbers(x)
            else {
                digits3DigitNumber <- rev(strsplit(as.character(x), "")[[1]])
                trim(paste(ones[digits3DigitNumber[3]], "hundred and", 
                           convert2DigitNumbers(makeNumber(digits3DigitNumber[2:1]))))
            }
        }
    } 
    
    convertThousands <- function(x) {
        if ( x > 0 && x <= 99999 ) {
            if ( x < 1000 ) convert3DigitNumbers(x)
            else {
                digitsThousands <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 9999 )
                    trim(paste(ones[digitsThousands[4]], "thousand", 
                               convert3DigitNumbers(makeNumber(digitsThousands[3:1]))))
                else 
                    trim(paste(convert2DigitNumbers(makeNumber(digitsThousands[5:4])), "thousand", 
                               convert3DigitNumbers(makeNumber(digitsThousands[3:1]))))  
            }
        }
    } 
    
    convertLakhs <- function(x) {
        if ( x > 0 && x <= 9999999 ) {
            if ( x < 100000 ) convertThousands(x)
            else {
                digitsLakhs <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 999999 )
                    trim(paste(ones[digitsLakhs[6]], "lakh", 
                               convertThousands(makeNumber(digitsLakhs[5:1]))))
                else 
                    trim(paste(convert2DigitNumbers(makeNumber(digitsLakhs[7:6])), "lakh", 
                               convertThousands(makeNumber(digitsLakhs[5:1]))))  
            }
        }
    } 
    
    convertCrores <- function(x) {
        if ( x > 0 && x <= 999999999 ) {
            if ( x < 10000000 ) convertLakhs(x)
            else {
                digitsCrores <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 99999999 )
                    trim(paste(ones[digitsCrores[8]], "crore", 
                               convertLakhs(makeNumber(digitsCrores[7:1]))))
                else 
                    trim(paste(convert2DigitNumbers(makeNumber(digitsCrores[9:8])), "crore", 
                               convertLakhs(makeNumber(digitsCrores[7:1]))))  
            }
        }
    } 
    
    trim <- function(text){
        #Tidy leading/trailing whitespace, space before comma
        text=gsub("^\ ", "", gsub("\ *$", "", gsub("\ ,",",",text)))
        
        #Clear any trailing " and"
        gsub(" and$","",text)
    }
    
    makeNumber <- function(...) as.numeric(paste(..., collapse=""))     
    
    #Disable scientific notation
    opts <- options(scipen=100) 
    on.exit(options(opts)) 
    
    ones <- c("zero", "one", "two", "three", "four", "five", "six", "seven",
              "eight", "nine") 
    names(ones) <- 0:9 
    
    teens <- c("ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
               "sixteen", " seventeen", "eighteen", "nineteen")
    names(teens) <- 0:9 
    
    tens <- c("twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
              "ninety") 
    names(tens) <- 2:9 
    
    x <- round(x)
    if (length(x) > 1 && x >= 0) return(trim(sapply(x, helper)))
    
    helper(x)
}

#################   CONVERT NUMBER TO WORDS IN EUROPEAN STYLE ######
numbers2wordsEurope <- function(x){
    helper <- function(x){
        if (x < 0) { return(paste(x, "is negative!")) }
        
        digits <- rev(strsplit(as.character(x), "")[[1]])
        nDigits <- length(digits)
        if (nDigits == 1) as.vector(ones[digits])
        else if (nDigits == 2)
            convert2DigitNumbers(x)
        else if (nDigits == 3) 
            convert3DigitNumbers(x)
        else if (nDigits >= 4 && nDigits <= 6) 
            convertThousands(x)
        else if (nDigits >= 7 && nDigits <= 9) 
            convertMillions(x)
        else if (nDigits >= 10 && nDigits <= 12) 
            convertBillions(x)
        else if (nDigits >= 13 && nDigits <= 15) 
            convertTrillions(x)
        else
            trim(paste(numbers2wordsEurope(floor(x/1000000000000)), "trillion", convertTrillions(x %% 1000000000000)))
    }
    
    convert2DigitNumbers <- function(x) {
        if ( x > 0 && x <= 99 ) {
            digits2DigitNumber <- rev(strsplit(as.character(x), "")[[1]])
            if (x <= 9) as.vector(ones[digits2DigitNumber])
            else if (x <= 19) as.vector(teens[digits2DigitNumber[1]])
            else {
                if (digits2DigitNumber[1][1] == "0") {
                    trim(paste(tens[digits2DigitNumber[2]]))
                }
                else {
                    trim(paste(tens[digits2DigitNumber[2]], as.vector(ones[digits2DigitNumber[1]])))
                }
            } 
        }
    } 
    
    convert3DigitNumbers <- function(x) {
        if ( x > 0 && x <= 999 ) {
            if ( x < 100 ) convert2DigitNumbers(x)
            else {
                digits3DigitNumber <- rev(strsplit(as.character(x), "")[[1]])
                trim(paste(ones[digits3DigitNumber[3]], "hundred and", 
                           convert2DigitNumbers(makeNumber(digits3DigitNumber[2:1]))))
            }
        }
    } 
    
    convertThousands <- function(x) {
        if ( x > 0 && x <= 999999 ) {
            if ( x < 1000 ) convert3DigitNumbers(x)
            else {
                digitsThousands <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 9999 )
                    trim(paste(ones[digitsThousands[4]], "thousand", 
                               convert3DigitNumbers(makeNumber(digitsThousands[3:1]))))
                else if ( x <= 99999 )
                    trim(paste(convert2DigitNumbers(makeNumber(digitsThousands[5:4])), "thousand", 
                               convert3DigitNumbers(makeNumber(digitsThousands[3:1]))))  
                else
                    trim(paste(convert3DigitNumbers(makeNumber(digitsThousands[6:4])), "thousand", 
                               convert3DigitNumbers(makeNumber(digitsThousands[3:1]))))  
            }
        }
    } 
    
    convertMillions <- function(x) {
        if ( x > 0 && x <= 999999999 ) {
            if ( x < 100000 ) convertThousands(x)
            else {
                digitsMillions <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 9999999 )
                    trim(paste(ones[digitsMillions[7]], "million", 
                               convertThousands(makeNumber(digitsMillions[6:1]))))
                else if ( x <= 99999999 )
                    trim(paste(convert2DigitNumbers(makeNumber(digitsMillions[8:7])), "million", 
                               convertThousands(makeNumber(digitsMillions[6:1]))))  
                else
                    trim(paste(convert3DigitNumbers(makeNumber(digitsMillions[9:7])), "million", 
                               convertThousands(makeNumber(digitsMillions[6:1]))))  
            }
        }
    } 
    
    convertBillions <- function(x) {
        if ( x > 0 && x <= 999999999999 ) {
            if ( x < 1000000000 ) convertMillions(x)
            else {
                digitsBillions <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 9999999999 )
                    trim(paste(ones[digitsBillions[10]], "billion", 
                               convertMillions(makeNumber(digitsBillions[9:1]))))
                else if ( x <= 99999999999 )
                    trim(paste(convert2DigitNumbers(makeNumber(digitsBillions[11:10])), "billion", 
                               convertMillions(makeNumber(digitsBillions[9:1]))))  
                else
                    trim(paste(convert3DigitNumbers(makeNumber(digitsBillions[12:10])), "billion", 
                               convertMillions(makeNumber(digitsBillions[9:1]))))  
            }
        }
    } 
    
    convertTrillions <- function(x) {
        if ( x > 0 && x <= 999999999999999 ) {
            if ( x < 1000000000000 ) convertBillions(x)
            else {
                digitsTrillions <- rev(strsplit(as.character(x), "")[[1]])
                if ( x <= 9999999999999 )
                    trim(paste(ones[digitsTrillions[13]], "trillion", 
                               convertBillions(makeNumber(digitsTrillions[12:1]))))
                else if ( x <= 99999999999999 )
                    trim(paste(convert2DigitNumbers(makeNumber(digitsTrillions[14:13])), "trillion", 
                               convertBillions(makeNumber(digitsTrillions[12:1]))))  
                else
                    trim(paste(convert3DigitNumbers(makeNumber(digitsTrillions[15:13])), "trillion", 
                               convertBillions(makeNumber(digitsTrillions[12:1]))))  
            }
        }
    } 
    
    trim <- function(text){
        #Tidy leading/trailing whitespace, space before comma
        text=gsub("^\ ", "", gsub("\ *$", "", gsub("\ ,",",",text)))
        
        #Clear any trailing " and"
        gsub(" and$","",text)
    }
    
    makeNumber <- function(...) as.numeric(paste(..., collapse=""))     
    
    #Disable scientific notation
    opts <- options(scipen=100) 
    on.exit(options(opts)) 
    
    ones <- c("zero", "one", "two", "three", "four", "five", "six", "seven",
              "eight", "nine") 
    names(ones) <- 0:9 
    
    teens <- c("ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
               "sixteen", " seventeen", "eighteen", "nineteen")
    names(teens) <- 0:9 
    
    tens <- c("twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
              "ninety") 
    names(tens) <- 2:9 
    
    x <- round(x)
    if (length(x) > 1 && x >= 0) return(trim(sapply(x, helper)))
    
    helper(x)
}

################   GLOBAL VARIABLES ##############
v_largest_number <- 999999999999999

# Define UI for application
ui <- fluidPage(
    theme = shinytheme("united"),
    tags$head(
        tags$style(
            HTML(".shiny-notification {
                             position:fixed;
                             top: calc(50%);
                             left: calc(50%);
                             font-family:Verdana;
                             fontSize:xx-large;
                             }
                             "
            )
        )
    ),
    
    # Application title
    fluidRow(
        column(width = 3,
               img(src="ParthaInPetra.jpg", width=200, height=112)
        ),
        column(width = 6,
               h1("SankhyaSaabdh", style="color:blue; text-align: center;"),
               h3("Number To Words Converter", style="color:darkred; text-align: center;")
        ),
        column(width = 3,
               h4("...", style="color:blue; text-align: right;"),
               h4("Developed by: Partha Majumdar", style="color:blue; text-align: right;"),
               h5("Riyadh (Saudi Arabia), 21-November-2019", style="color:black; text-align: right;")
        )
    ),
    
    fluidRow(
        column(width =  4,
               wellPanel(
                   fluidRow(
                       numericInput("v_input", 
                                    h3("Enter a Number", style="color:blue; text-align: center;"), 
                                    value = "100") 
                   ),
                   fluidRow(
                       wellPanel(
                           p("To learn how to use SankhyaSaabdh, visit the ",
                             a("SankhyaSaabdh Demonstration Video.", 
                               href = "https://youtu.be/Gbhy1atxybo", 
                               target="_blank")
                           )
                       )
                   )
               )
        ),
        column(width = 8,
               fluidRow(
                   column(width = 12,
                          wellPanel(
                              h4("Number being Converted", style="color:black; text-align: center;"),
                              h2(textOutput("rawNumber"), style="color:darkgreen; text-align: center;")
                          ),
                          wellPanel(
                              h4("European Style", style="color:black; text-align: center;"),
                              h2(textOutput("europeanStyle"), style="color:blue; text-align: center;")
                          ),
                          wellPanel(
                              h4("Indian Style", style="color:black; text-align: center;"),
                              h2(textOutput("indianStyle"), style="color:orange; text-align: center;")
                          )
                   )
               )
        )
    )
)

# Define server logic required
server <- function(input, output, session) {
    
    output$rawNumber <- renderText({
        req(input$v_input)
        return(format(round(input$v_input, 0), nsmall = 0, big.mark = ","))
    })
    
    output$europeanStyle <- renderText({
        req(input$v_input)
        # english::english(input$v_input)
        return(
            ifelse(input$v_input <= v_largest_number,
                   numbers2wordsEurope(round(input$v_input,0)),
                   "Number too large"
            )
        )
    })
    
    output$indianStyle <- renderText({
        req(input$v_input)
        return(
            ifelse(input$v_input <= v_largest_number,
                   numbers2wordsIndia(round(input$v_input,0)),
                   "Number too large"
            )
        )
    })
}

# Run the application 
shinyApp(ui = ui, server = server)
## 
## Listening on http://127.0.0.1:6514

Advertisements

This site uses Akismet to reduce spam. Learn how your comment data is processed.