Highcharter Unlimited Drill down using R - r

I looked at this SO question, that SO question. I followed this github method check out ISSUES to help get ideas on how to solve this.
Step 1: Copy the following into text editor and save as test.csv file:
My datasource is NVD JSON FEEDS which I processed and cleaned and created this dataset with the first 25 rows shown here.
Year,Vendor name,Product name,CVE,Major,Minor,Build,Revision
1988,eric_allman,sendmail,CVE-1999-0095,5,5.58,,
1988,ftp,ftp,CVE-1999-0082,*,,,
1988,ftpcd,ftpcd,CVE-1999-0082,*,,,
1989,bsd,bsd,CVE-1999-1471,4,4.2,,
1989,bsd,bsd,CVE-1999-1471,4,4.3,,
1989,sun,sunos,CVE-1999-1122,4,4.0,,
1989,sun,sunos,CVE-1999-1122,4,4.0,4.0.1,
1989,sun,sunos,CVE-1999-1122,4,4.0,4.0.3,
1989,sun,sunos,CVE-1999-1467,4,4.0,,
1989,sun,sunos,CVE-1999-1467,4,4.0,4.0.1,
1989,sun,sunos,CVE-1999-1467,4,4.0,4.0.2,
1989,sun,sunos,CVE-1999-1467,4,4.0,4.0.3,
1989,sun,sunos,CVE-1999-1467,4,4.0,4.0.3c,
1990,digital,vms,CVE-1999-1057,5,5.3,,
1990,freebsd,freebsd,CVE-2000-0388,3,3.0,,
1990,freebsd,freebsd,CVE-2000-0388,3,3.1,,
1990,freebsd,freebsd,CVE-2000-0388,3,3.2,,
1990,freebsd,freebsd,CVE-2000-0388,3,3.3,,
1990,freebsd,freebsd,CVE-2000-0388,3,3.4,,
1990,hp,apollo_domain_os,CVE-1999-1115,sr10,sr10.2,,
1990,hp,apollo_domain_os,CVE-1999-1115,sr10,sr10.3,,
1990,next,nex,CVE-1999-1392,1,1.0a,,
1990,next,next,CVE-1999-1198,2,2.0,,
1990,next,next,CVE-1999-1391,1,1.0,,
1990,next,next,CVE-1999-1391,1,1.0a,,
Step 2: Copy and paste following code into R and run it:
My codes follow this SO question especially the discussion by #NinjaElvis. I think it is possible to create 3 levels or more. Just doing more research and figuring out.
############################
suppressPackageStartupMessages(library("highcharter"))
library("dplyr")
library("purrr")
library("data.table")
second_el_to_numeric <- function(ls){
map(ls, function(x){
x[[2]] <- as.numeric(x[[2]])
x
})
}
cve_affected_product <- fread("test.csv")
# LAYER ONE YEAR DRILLDOWN VIEW #########################
Year <- cve_affected_product[,c(1:2)]
Year <- unique(Year[,list(Year,`Vendor name`)])
Year <- Year[,c(1)][,count:=1]
Year <- setDT(aggregate(.~ Year ,data=Year,FUN=sum))
#setorder(Year, Year, `Vendor name`)
years_df <- tibble(
name = c(Year$Year),
y = c(Year$count),
drilldown = tolower(paste(name,'id'))
)
ds <- list_parse(years_df)
names(ds) <- NULL
# Vendor View HC ###########
hc <- highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "Basic drilldown") %>%
hc_xAxis(type = "category") %>%
hc_yAxis(visible = FALSE,reversed = FALSE) %>%
hc_legend(enabled = FALSE) %>%
hc_plotOptions(
series = list(
boderWidth = 0,
dataLabels = list(enabled = TRUE)
)
) %>%
hc_add_series(
name = "Vendors",
colorByPoint = TRUE,
data = ds
)
# LAYER TWO VENDOR DRILLDOWN VIEW #########################
Vendor <- cve_affected_product[,c(1:3)]
Vendor <- unique(Vendor[,list(Year,`Vendor name`,`Product name`)])
Vendor <- Vendor[,c(1:2)][,count:=1]
Vendor <- setDT(aggregate(.~ Year+`Vendor name` ,data=Vendor,FUN=sum))
setorder(Vendor, Year, `Vendor name`)
years <- as.character(unique(Vendor$Year))
for(i in 1:length(years)){
tempdf <- Vendor[Vendor$Year==years[i],]
dfname <- paste("df",years[i],sep="")
dsname <- paste("ds",years[i],sep="")
X <- tibble(
name = c(tempdf$`Vendor name`),
y = c(tempdf$count),
drilldown = tolower(paste(name,'id'))
)
Y <- second_el_to_numeric(list_parse2(assign(dfname,X)))
assign(dsname,Y)
}
# Vendor View HC ###########
hc <- hc %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(
id = "1988 id",
data = ds1988,
colorByPoint = TRUE,
keys = list('name','y','drilldown')
),
list(
id = "1989 id",
data = ds1989,
keys = list('name','y','drilldown')
),
list(
id = "1990 id",
data = ds1990,
keys = list('name','y','drilldown')
)#,
)
)
# LAYER THREE PRODUCT DRILLDOWN VIEW #########################
Product <- cve_affected_product[,c(1:4)]
Product <- unique(Product[,list(Year,`Vendor name`,`Product name`, CVE)])
Product <- Product[,c(1:3)][,count:=1]
Product <- setDT(aggregate(.~ Year+`Vendor name`+`Product name` ,data=Product,FUN=sum))
setorder(Product, Year, `Vendor name`,`Product name`)
vendors <- as.character(unique(Product$`Vendor name`))
for(i in 1:length(vendors)){
tempdf <- Product[Product$`Vendor name`==vendors[i],]
dfname <- paste("df",vendors[i],sep="")
dsname <- paste("ds",vendors[i],sep="")
X <- tibble(
name = c(tempdf$`Product name`),
y = c(tempdf$count),
drilldown = tolower(paste(name,'id'))
)
Y <- second_el_to_numeric(list_parse2(assign(dfname,X)))
assign(dsname,Y)
}
# Product View HC ###########
hc <- hc %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(
id = "eric_allman id",
data = dseric_allman,
keys = list('name','y','drilldown')
),
list(
id = "ftp id",
data = dsftp,
keys = list('name','y','drilldown')
),
list(
id = "ftpcd id",
data = dsftpcd,
keys = list('name','y','drilldown')
),
list(
id = "bsd id",
data = dsbsd,
keys = list('name','y','drilldown')
),
list(
id = "sun id",
data = dssun,
keys = list('name','y','drilldown')
),
list(
id = "digital id",
data = dsdigital,
keys = list('name','y','drilldown')
),
list(
id = "freebsd id",
data = dsfreebsd,
keys = list('name','y','drilldown')
),
list(
id = "hp id",
data = dshp,
keys = list('name','y','drilldown')
),
list(
id = "next id",
data = dsnext,
keys = list('name','y','drilldown')
)#,
)
)
# LAYER FOUR CVE DRILLDOWN VIEW #########################
Product_CVE <- cve_affected_product[,c(1:5)]
Product_CVE <- unique(Product_CVE[,list(Year,`Vendor name`,`Product name`, CVE, Major)])
Product_CVE <- Product_CVE[,c(1:4)][,count:=1]
Product_CVE <- setDT(aggregate(.~ Year+`Vendor name`+`Product name`+CVE ,data=Product_CVE,FUN=sum))
setorder(Product_CVE, Year, `Vendor name`,`Product name`, CVE)
products <- as.character(unique(Product_CVE$`Product name`))
for(i in 1:length(products)){
tempdf <- Product_CVE[Product_CVE$`Product name`==products[i],]
ifelse(tempdf$`Vendor name`==tempdf$`Product name`,
dfname <- paste("df_",products[i],sep=""),
dfname <- paste("df",products[i],sep=""))
ifelse(tempdf$`Vendor name`==tempdf$`Product name`,
dsname <- paste("ds_",products[i],sep=""),
dsname <- paste("ds",products[i],sep=""))
X <- tibble(
name = gsub("-", "", c(tempdf$CVE)),
y = c(tempdf$count),
drilldown = tolower(paste(name,'id'))
)
Y <- second_el_to_numeric(list_parse2(assign(dfname,X)))
assign(dsname,Y)
}
# CVE View HC ###########
hc <- hc %>%
hc_drilldown(
allowPointDrilldown = TRUE,
series = list(
list(
id = "sendmail id",
data = dssendmail,
keys = list('name','y','drilldown')
),
list(
id = "ftp id",
data = ds_ftp,
keys = list('name','y','drilldown')
),
list(
id = "ftpcd id",
data = ds_ftpcd,
keys = list('name','y','drilldown')
),
list(
id = "bsd id",
data = ds_bsd,
keys = list('name','y','drilldown')
),
list(
id = "sunos id",
data = dssunos,
keys = list('name','y','drilldown')
),
list(
id = "vms id",
data = dsvms,
keys = list('name','y','drilldown')
),
list(
id = "freebsd id",
data = ds_freebsd,
keys = list('name','y','drilldown')
),
list(
id = "apollo_domain_os id",
data = dsapollo_domain_os,
keys = list('name','y','drilldown')
),
list(
id = "nex id",
data = dsnex,
keys = list('name','y','drilldown')
),
list(
id = "next id",
data = ds_next,
keys = list('name','y','drilldown')
)
)
)
Output First Level:
Output Second Level Clicking on 1988:
ISSUES:
I should be able to click on vendor eric_allman and get a drill down, however I am not. I want to be able to drill down all the way to Revision if it exists. This is just prototypying new functionality for my app to get it working. However, highcharter does not make this easy or efficient. My dataset has almost 4 million observations. That will be the next struggle how to handle that.
I am even considering using D3 by creating a JSON file in python if I cannot do it using R. However, creating the JSON file in python is not trivial but doable. I am currently working on python code as a back up.
Thank you for the help and any suggestions

Interestingly enough after posting this question, i decided to do more research, since most of the research was pointing me to example of how to do it in javascript. Google search took me to this SO response by #K. Rohde
This post is from 2015 and I really appreciate how he explained the two different approaches. I ended up using hybrid approach borrowing from both.
For those interested in seeing how the drill down is working, go to my shiny app. Once you on the page Click on Visualizations, then "Drill Down For Vendor CVE Affected Products Versions and Revisions"and try it out. Again I would not have done it without #K. Rohde write up.

Related

ShinyApp in R - Contrast Error of having Factor of level 1 with Radiobutton Inputs

I'm building a Shiny Application using R , basically it takes a dataset and runs it through several models - Classification / Regression.
The problem i am facing now is , I take inputs from the user with some being numeric and some being factors. The Factor inputs always have one level since we are using Radiobuttons to select a value.
radioButtons("HomeOwner", "Does the Customer own a home?", choiceNames=c('Yes', 'No'), choiceValues = c(1,0)),
radioButtons("Debt", "Does the Customer has existing debt?", choiceNames=c('Yes', 'No'), choiceValues = c(1,0)),
So my dataframe from the building the model has Factors for 3 variables and so does my input data frame from the user but the levels are one since i need to know if they select Yes or No.
Below is the Dataframe :
When i try to predict using the model created , i get the contrast error because of my input dataframe having factor of 1 in three variables , i need them to be factors or is there any way to solve this?
Edit 1 : Whole App
# Application Start
# Initiating Library
source("Functions.R")
library(shiny)
library(shinythemes)
#########################Start of ShinyApp Code#######################################
# Install the shiny and shinythemes packages
# install.packages('shiny')
# install.packages('shinythemes')
# Create the user interface (ui) where you will take the input and display the output
#ui <- fluidpage()
ui <- fluidPage(shinythemes::themeSelector(),
titlePanel("Assignment-AIPM"),
sidebarLayout(
sidebarPanel(
selectInput("selectds","Select the dataset to work with",
choices = c("Boston Housing Dataset"=1,
"Customer Profit Dataset"=2,
"Financial Dataset"=3,
"Education Tech Dataset"=4)
),
br(),
actionButton("runmodels","Run Models"),
),
mainPanel(
navbarPage("Information",
tabPanel("Input",uiOutput("myInput")),
tabPanel("Output",tableOutput("myOutput")),
tabPanel("Plots",plotOutput("myPlot"))
)
)
)
) # fluidPage
# https://stackoverflow.com/questions/30906325/shiny-use-column-headers-from-read-in-file-as-selectinput-choices - To select
# Input from a datapath using the columns
# https://stackoverflow.com/questions/54205476/how-to-execute-a-function-in-the-shiny-server-depending-on-the-inputid-value-of/54220548
# Function Execution
# Define server function
server <- function(input, output, session)
{
observeEvent(input$runmodels,
{
############################# Boston House Prediction
if(input$selectds == 1 )
{
print("Entering Boston House Prediction Input")
output$myInput <- renderUI({
tagList(tags$h3("Enter the details of the Land:"),
radioButtons("CHAS", "Near Charles River or Not", choiceNames=c('Yes', 'No'), choiceValues = c('1','0')),
numericInput("CRIM", "Criminal Rate 1 - 5", 1, min=1, max=5),
numericInput("ZN", "Proportion of Land Zone over 25,000 SQFT", 1),
numericInput("INDUS", "Proportion of Industrial Business in the town", 1),
numericInput("RM", "Average Number of Rooms Per Dwelling", 1),
numericInput("NOX", "Tenure in No. of Years", 1),
numericInput("AGE", "Proportion of Owner Occupied Buildings prior 1940", 1),
numericInput("DIS", "Weighted Distances to Boston Employment Centre", 1),
numericInput("RAD", "Radial Access to highways", 1),
numericInput("TAX", "Full Value Property rate per 10,000$", 1),
numericInput("PTRATIO", "Pupil - Teacher Ratio in Town", 1),
numericInput("B", "Proportion of Black Population in Town", 1),
numericInput("LSTAT", "Percentage of Lower Status Population", 1),
HTML("<br> <br>")
)
})
data_input = reactive({
data.frame(CHAS = factor(input$CHAS),
CRIM = input$CRIM,
ZN = input$ZN,
INDUS = input$INDUS,
NOX = input$NOX,
RM = input$RM,
AGE = input$AGE,
DIS = input$DIS,
RAD = input$RAD,
TAX = input$TAX,
PTRATIO = input$PTRATIO,
B = input$B,
LSTAT = input$LSTAT)
})
regressor_linear <- boston_linear_reg()
data_output = reactive({
data.frame(Logistic_regression = predict(regressor_linear,type='response',data_input())
)
})
output$myOutput <- renderTable({data_output()})
}
############################################### Customer Profit
if(input$selectds == 2 )
{
print("Entering Customer Profit User Input")
output$myInput <- renderUI({
tagList(tags$h3("Enter the details of the customer:"),
radioButtons("Online", "Online Customer?", choiceNames=c('Yes', 'No'), choiceValues = c('1','0')),
radioButtons("Age", "Whats your Customer Age Group?", choiceNames=c('0-10','10-20','20-30','30-40','40-50','50-60','60-70'), choiceValues = c('1','2','3','4','5','6','7')),
radioButtons("Income", "Whats your Customer Income Group?", choiceNames=c('5k-10k','10k-15k','15k-20k','20k-25k','25k-30k','30k-35k','35k-40k','40k-50k','50k+'), choiceValues = c('1','2','3','4','5','6','7','8','9')),
numericInput("Tenure", "Tenure in No. of Years", 1),
HTML("<br> <br>"))
})
data_input = reactive({
data.frame(Online = as.integer(input$Online),
Age = as.integer(input$Age),
Inc = as.integer(input$Income),
Tenure = as.numeric(input$Tenure))
})
regressor_linear <- customer_linear_reg()
classifier_Rforest <- customer_RForest_Regression()
classifier_NNet <- customer_NeuralNet()
data_output = reactive({
data.frame(Linear_regression = predict(regressor_linear,data_input()),
Random_Forest_Prediction = predict(classifier_Rforest,data_input()),
Neural_Net_Prediction = as.data.frame(h2o.predict(classifier_NNet, newdata = as.h2o(data_input())))
)
})
output$myOutput <- renderTable({data_output()})
}
########################## Financial set
if(input$selectds == 3 )
{
print("Entering Finanical User Input")
output$myInput <- renderUI({
tagList(numericInput("Age", "Please enter the Customer Age(1-100)", 25, min=1, max=100),
numericInput("Income", "Please enter Customer monthly Income(0-100000$)", 3500, min=0, max=100000),
radioButtons("HomeOwner", "Does the Customer own a home?", choiceNames=c('Yes', 'No'), choiceValues = c(1,0)),
radioButtons("Debt", "Does the Customer has existing debt?", choiceNames=c('Yes', 'No'), choiceValues = c(1,0)),
numericInput("EmpPeriod", "Please enter the Customer employement period in months", 45),
numericInput("AccPeriod", "Please enter Customer Account Age in months",45),
numericInput("Amount", "Please enter Amount Requested($)",1000),
radioButtons("PaySchedule", "Please enter Pay Schedule", choiceNames=c('bi-weekly', 'weekly', 'semi-monthly','monthly'), choiceValues = c(1,2,3,4)),
numericInput("CurrAddress", "Please enter the Customer currnt address period in months", 45),
numericInput("RiskScore", "Please enter Customer Risk Score (1-100000",40000),
numericInput("Enquiry", "Please enter Customer enquiries last month",5),
actionButton("Predict", "Predict Sanction"))
})
observeEvent(input$Predict, {
data_input = reactive({
data.frame(
home_owner = factor(input$HomeOwner),
age = as.numeric(input$Age),
income = as.numeric(input$Income),
has_debt = factor(input$Debt),
amount_requested = input$Amount,
employment_period = input$EmpPeriod,
personal_account_period = input$AccPeriod,
pay_schedule = factor(input$PaySchedule),
current_address_period = input$CurrAddress,
inquiries_last_month = as.integer(input$Enquiry),
risk_score = input$RiskScore
)
})
logistic_regressor = financial_logistic_regression()
Single_DT = financial_DT()
#classifier_svm = financial_svm()
str(data_input())
data_output = reactive({
data.frame(Logistic_regression = predict(logistic_regressor,type='response',newdata=data_input()),
#Support_vector_machine = predict(classifier_svm, type = 'response', newdata = data_input())
Single_Decision_Tree = predict(Single_DT$classifier, type = 'class', newdata = data_input())
)
})
output$myPlot <- renderPlot({rpart.plot::rpart.plot(Single_DT$classifier)})
output$myOutput <- renderTable({data_output()})
})
}
Functions.R
#Functions for Shiny Assignement
library(caret)
library(ROCR)
library(Metrics)
library(dplyr)
library(caTools)
library(e1071)
library(zoo)
library(car)
library(rpart)
library(randomForest)
library(rpart.plot)
library(h2o)
library(data.table)
# Global Datasets
bostonds <- read.csv('Datasets/02_Boston.csv')
customerds <- read.csv('Datasets/01_CustomerProfit_Regression.csv')
financialds <- read.csv('Datasets/04_P39_Financial_Data.csv')
edtechds <- read.csv('Datasets/05_Lead_Scoring.csv')
boston_linear_reg <- function()
{
set.seed(1234)
data_nomiss = bostonds %>% select(CRIM,ZN,INDUS,CHAS,NOX,RM,AGE,DIS,RAD,
TAX,PTRATIO,B,LSTAT,MEDV) %>% na.omit()
data_nomiss$CHAS = factor(data_nomiss$CHAS)
regressor_lm = lm(formula = MEDV ~ .,data=data_nomiss)
return(regressor_lm)
#medv_predict = predict(regressor,test_ds)
}
customer_linear_reg <- function()
{
data_nomiss = customerds %>% select(Profit,Online,Age,Inc,Tenure) %>% na.omit()
#data_nomiss$Online = factor(data_nomiss$Online)
set.seed(123)
regressor_lm = lm(formula = Profit ~ Online + Inc + Age + Tenure
, data = data_nomiss,na.action = na.omit)
str(data_nomiss)
return(regressor_lm)
#profit_predict = predict(regressor, newdata=test_set)
}
customer_RForest_Regression <- function()
{
######## Data Processing and Cleanup starts here
dataset = customerds
# Creating a new dataset called 'data_nomiss' which will have no missing data
data_nomiss = dataset %>%
select(Profit,Online,Age,Inc,Tenure) %>%
na.omit()
#data_nomiss$Online = factor(data_nomiss$Online)
#data_nomiss$Age = factor(data_nomiss$Age, labels = c('0-10','10-20','20-30','30-40','40-50','50-60','60-70'),levels = c('1','2','3','4','5','6','7'))
#data_nomiss$Inc = factor(data_nomiss$Inc, labels = c('5k-10k','10k-15k','15k-20k','20k-25k','25k-30k','30k-35k','35k-40k','40k-50k','50k+'),levels = c('1','2','3','4','5','6','7','8','9'))
# Factor Variables
#data_nomiss[,1] = scale(data_nomiss[,1])
#data_nomiss[,5] = scale(data_nomiss[,5])
########### Data Processing and Cleanup ends here
set.seed(123)
classifier = randomForest(Profit ~ .,data=data_nomiss,na.action = na.omit,ntree=100)
return(classifier)
}
customer_NeuralNet <- function()
{
dataset = customerds
data_nomiss = dataset %>%
select(Profit,Online,Age,Inc,Tenure) %>%
na.omit()
set.seed(123)
h2o.init(nthreads = -1)
classifier = h2o.deeplearning(y = 'Profit',
training_frame = as.h2o(data_nomiss),
activation = 'Tanh',
hidden = c(10),
epochs = 100,
train_samples_per_iteration = -2)
return(classifier)
}
############################### Financial Dataset
financial_pre_process <- function(ds)
{
####################Data Processing and Clean up Start#############################
data_nomiss = ds %>% select(age,pay_schedule,home_owner,income,
months_employed,years_employed,current_address_year,
personal_account_m,personal_account_y,has_debt,
amount_requested,risk_score,risk_score_2,
risk_score_3,risk_score_4,risk_score_5,
ext_quality_score,ext_quality_score_2,
inquiries_last_month,e_signed) %>% na.omit()
data_nomiss$e_signed = factor(data_nomiss$e_signed)
data_nomiss$home_owner = factor(data_nomiss$home_owner)
data_nomiss$has_debt = factor(data_nomiss$has_debt)
data_nomiss$pay_schedule = factor(data_nomiss$pay_schedule,
levels = c('weekly','bi-weekly','monthly','semi-monthly'),
labels = c(1,2,3,4))
data_nomiss$employment_period = data_nomiss$months_employed + (data_nomiss$years_employed * 12)
data_nomiss$personal_account_period = data_nomiss$personal_account_m + (data_nomiss$personal_account_y * 12)
data_nomiss$current_address_period = data_nomiss$current_address_year * 12
data_nomiss = select(data_nomiss,-c(months_employed,years_employed,personal_account_m,personal_account_y,current_address_year))
data_nomiss[,1] = scale(data_nomiss[,1]) # Age
data_nomiss[,4] = scale(data_nomiss[,4]) # Income
data_nomiss[,6:14] = scale(data_nomiss[,6:14]) # Amount Requested -> Risk score
data_nomiss[,16:18] = scale(data_nomiss[,16:18]) # Created Columns
data_nomiss[,1] = apply(data_nomiss[,1], 1, as.numeric)
data_nomiss[,4] = apply(data_nomiss[,4], 1, as.numeric)
return(data_nomiss)
####################Data Processing and Clean up End#############################
}
financial_logistic_regression <- function()
{
ds = financialds
set.seed(1234)
data_nomiss = financial_pre_process(ds)
str(data_nomiss)
classifier_log = glm(formula = e_signed ~ age+pay_schedule+current_address_period+home_owner+income+employment_period+has_debt+amount_requested+personal_account_period+risk_score+inquiries_last_month,
family = binomial,
data = data_nomiss)
return(classifier_log)
}
financial_svm <- function()
{
ds = financialds
set.seed(1234)
data_nomiss = financial_pre_process(ds)
classifier_svm = svm(formula = e_signed ~ age+pay_schedule+current_address_period+home_owner+income+employment_period+has_debt+amount_requested+personal_account_period+risk_score+inquiries_last_month,
data = data_nomiss,
type = 'C-classification',
kernel = 'radial')
return(classifier_svm)
}
financial_DT <- function()
{
ds = financialds
set.seed(1234)
data_nomiss = financial_pre_process(ds)
classifier_DT = rpart(formula = e_signed ~ age+pay_schedule+current_address_period+home_owner+income+employment_period+has_debt+amount_requested+personal_account_period+risk_score+inquiries_last_month,
data = data_nomiss)
result <- list()
result$classifier <- classifier_DT
result$plot <- rpart.plot::rpart.plot(classifier_DT)
return(result)
}
financial_RForest <- function()
{
ds = financialds
set.seed(1234)
data_nomiss = financial_pre_process(ds)
classifier_RForest = randomForest(x= training_set[-15],
y= training_set$e_signed,
ntree=1500)
result <- list()
result$classifier <- classifier_RForest
result$plot <- rpart.plot::rpart.plot(classifier_RForest)
return(result)
}
}

How do you specify variables when rending a formattable table in shiny?

I'm trying to create and render an interactive formattable table in a shiny app.
Here is a sample dataframe:
tcharts <- data.frame(pgm = c(1,2,3,4,5,6,7,8),
horse = c("Cigar", "Funny Cide", "Animal Kingdom", "Blame", "Zenyatta", "New Years Day", "Northern Dancer", "Beautiful Pleasure"),
groundloss = c(55,70,85,42,90,45,53,50),
distanceRun = c(5050,5070,5085,5045,5090,5045,5053,5050),
ttl = c(50,70,85,42,90,45,53,50),
fps = c(52.3,51.8,51.9,52.0,53.6,52.9,53.7,53.1),
finishTime = c(52.3,51.8,51.9,52.0,53.6,52.9,53.7,53.1),
finish = c(4,7,1,2,5,6,3,8),
BL = c(0,1,2,6,2,9,6,8),
rnum = c(1,1,1,1,1,1,1,1),
sixteenth = c(330,330,330,330,330,330,330)
)
Working version
This version of the code, when list() is empty (use all variables in dataframe) produces a table as expected.
library(shiny)
library(formattable)
inputPanel(
selectInput("rnum", label = "Race Number:",
choices = c(1,2,3,4,5,6,7,8,9), selected = 1),
sliderInput("poc", label = "Point of Call:",
min = 330, max = 5280, value = 330, step = 330)
)
cdat <- reactive({
tcharts %>% filter(rnum %in% input$rnum) %>%
filter(Sixteenth %in% input$poc)
})
renderFormattable({
formattable(cdat(),list(
))
})
Error Version:
With this version, I get an ERROR: object pgm not found
library(shiny)
library(formattable)
inputPanel(
selectInput("rnum", label = "Race Number:",
choices = c(1,2,3,4,5,6,7,8,9), selected = 1),
sliderInput("poc", label = "Point of Call:",
min = 330, max = 5280, value = 330, step = 330)
)
cdat <- reactive({
tcharts %>% filter(rnum %in% input$rnum) %>%
filter(Sixteenth %in% input$poc)
})
renderFormattable({
formattable(cdat(),list(
pgm,
Horse
))
})
The error message leads me to believe I'm not specifying the variable correctly, but I'm not sure how to do it. I'v looked at several formattable / shiny SO questions and responses, but have not come up with the correct sytax.

Adding groupcheckboxinput values to data frame in Shiny

I am attempting to add the values from a checkboxgroupinput value to the data frame called surv_data in a Shiny App.
Below is the code for the check boxes:
checkboxGroupInput(inputId = "variables", label = "",
choices = c(
"Covariate 1" = "cov1",
"Covariate 2" = "cov2"
),
selected = c('cov1', 'cov2'))
Here is where I combine the variables in to one data frame:
surv_data <- reactive({
raw_surv <- raw_surv_data()
data.frame(
Time = raw_surv[[input$Time]],
Treatment = raw_surv[[input$Treatment]],
endpoint = raw_surv[[input$Endpoint]]
)
})
I need to somehow add the values cov1 and cov2 below the following line:
endpoint = raw_surv[[input$Endpoint]]
I've attempted to add variables = raw_surv[[input$variables]] but unfortunately this does not work. Any help would be appreciated.
Maybe
surv_data <- reactive({
raw_surv <- raw_surv_data()
cbind(
data.frame(
Time = raw_surv[[input$Time]],
Treatment = raw_surv[[input$Treatment]],
endpoint = raw_surv[[input$Endpoint]]
),
raw_surv[input$variables]
)
})

The networkd3 is displaying all data, not the subset I want to show based on widget inputs in Shiny app

I am trying to make a Shiny app where the user selects a few options and a network and data table will display based on the inputs. I have a diet study database and would like users to be able to specify the predator species they are interested in, the diet metric (weight, volumetric, etc) and the taxonomic level they want nodes identified to. The data table works fine (so I did not include the code) and updates based on the input but the network does not change, it only shows all of the data. When I run the code for generating the plot outside of Shiny it works fine. This is my first shiny attempt so any suggestions would be greatly appreciated.
library(dplyr)
library(igraph)
library(networkD3)
Diet <-data.frame(
Predator_Scientific_Name = rep("Acanthocybium solanderi", 10),
Class_Predator = rep("Actinopterygii", 10),
Order_Predator = rep("Perciformes", 10),
Family_Predator = rep("Scombridae", 10),
Genus_Predator = rep("Acanthocybium", 10),
Species_Predator = rep("solandri", 10),
Class_Prey = rep("Actinopterygii", 10),
Order_Prey = c( "Clupeiformes" , NA , "Perciformes", "Perciformes", "Perciformes", "Perciformes", "Perciformes", "Perciformes", "Tetraodontiformes", "Tetraodontiformes"),
Family_Prey = c("Clupeidae", NA, "Coryphaenidae", "Carangidae", "Scombridae","Echeneidae","Carangidae", "Scombridae", "Balistidae","Diodontidae"),
Genus_Prey = c("Sardinella", NA, "Coryphaena", "Decapterus", "Euthynnus", NA, NA, NA, "Balistes", "Diodon"),
Species_Prey = c("aurita" , "", "hippurus", "punctatus","alletteratus", "", "", "","capriscus", "spp." ),
Lowest_Taxonomic_Identification_Prey = c("Sardinella aurita","Actinopterygii","Coryphaena hippurus","Decapterus punctatus","Euthynnus alletteratus", "Echeneidae", "Carangidae","Scombridae","Balistes capriscus","Diodon spp."),
Frequency_of_Occurrence = c(2.8, 59.1, 1.4, 7.0, 1.4, 1.4, 15.5, 21.1, 2.8, 4.2), StringAsFactors = FALSE
)
pred.name <- unique(Diet$Predator_Scientific_Name)
prey.tax <- unique(Diet$Lowest_Taxonomic_Identification_Prey)
#Progress bar function
compute_data <- function(updateProgress = NULL) {
# Create 0-row data frame which will be used to store data
dat <- data.frame(x = numeric(0), y = numeric(0))
for (i in 1:10) {
Sys.sleep(0.25)
# Compute new row of data
new_row <- data.frame(x = rnorm(1), y = rnorm(1))
# If we were passed a progress update function, call it
if (is.function(updateProgress)) {
text <- paste0("x:", round(new_row$x, 2), " y:", round(new_row$y, 2))
updateProgress(detail = text)
}
# Add the new row of data
dat <- rbind(dat, new_row)
}
dat
}
####
# Define UI for application that draws a histogram
ui <- dashboardPage(
skin = "blue",
dashboardHeader(title = "Diet Database"),
dashboardSidebar(
sidebarMenu(
menuItem("Parameters",
tabName = "paramaters",
icon = shiny::icon("bar-chart")))
),
dashboardBody(
tabItems(
tabItem(
tabName = "paramaters",
fluidRow(
shiny::column(
width = 4,
shinydashboard::box(
title = "Predator",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = NULL,
shiny::helpText("Select a predator to view its connections and prey items:"),
shiny::selectInput(
"pred",
shiny::h5("Predator Scientific Name:"),
c(NA,pred.name))),
shinydashboard::box(
title = "Prey",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = NULL,
shiny::helpText("Select a prey taxa to view its connections and predators:"),
shiny::selectInput(
"prey",
shiny::h5("Prey Taxa:"),
c(NA,prey.tax))),
shinydashboard::box(
title = "Diet Metric",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = NULL,
shiny::helpText("Select a diet metric to use:"),
shiny::selectInput(
"dietmetric",
shiny::h5("Diet Metric:"),
c("Frequency of Occurrence" = "Frequency_of_Occurrence",
"Wet Weight" = "Weight",
"Dry Weight" = "Dry_Weight",
"Volume" = "Volume",
"Index of Relative Importance" = "IRI",
"Index of Caloric Importance" = "ICI",
"Number" = "Number"))),
shinydashboard::box(
title = "Taxonomic Level",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = NULL,
shiny::helpText("Select a taxonomic level of nodes:"),
shiny::selectInput(
"nodetax",
shiny::h5("Taxonomic Level:"),
c("Order" = "Order",
"Family" = "Family",
"Genus" = "Genus",
"Species" = "Species"))),
shinydashboard::box(
title = "Generate Network",
status = "primary",
solidHeader = T,
collapsible = T,
width = NULL,
actionButton("makenet", "Generate")
)
),
#Area for network to be displayed
shiny::column(
width = 8,
shinydashboard::box(
title = "Trophic Network",
status = "primary",
solidHeader = TRUE,
collapsible = FALSE,
width = NULL,
forceNetworkOutput("netplot")
)
)
))
)))
server <- function(input, output, session) {
network.data <- eventReactive(input$makenet, {
edgelist <- Diet %>% filter(Predator_Scientific_Name == input$pred|Lowest_Taxonomic_Identification_Prey == input$prey
) %>% select(
paste(input$nodetax, "Predator", sep = "_"),
Class_Predator,
paste(input$nodetax, "Prey", sep = "_"),
Class_Prey,
input$dietmetric
)
colnames(edgelist) <- c("SourceName",
"SourceClass",
"TargetName",
"TargetClass",
"Weight")
edgelist <- edgelist[complete.cases(edgelist),]
})
output$netplot <- renderForceNetwork( {
network.data()
ig <-igraph::simplify(igraph::graph_from_data_frame(edgelist[,c(1,3,5)], directed = TRUE))
SourceID <- TargetID <- c()
for (i in 1:nrow(edgelist)) {
SourceID[i] <- which(edgelist[i,1] == V(ig)$name)-1
TargetID[i] <- which(edgelist[i,3] == V(ig)$name)-1
}
#Create edgelist that contains source and target nodes and edge weights
edgeList <- cbind(edgelist, SourceID, TargetID)
nodeList <- data.frame(ID = c(0:(igraph::vcount(ig) - 1)),
nName = igraph::V(ig)$name)
#Determine and assign groups based on class
preddf <-
data.frame(SciName = edgelist[, 1], class = edgelist[, 2])
preydf <-
data.frame(SciName = edgelist[, 3], class = edgelist[, 4])
groupsdf <- rbind(preddf, preydf)
groupsdf <- groupsdf %>% mutate(SciName = as.character(SciName),
class = as.character(class))
nodeGroup <- c()
for (i in 1:nrow(nodeList)) {
index <- which(groupsdf[, 1] == nodeList$nName[i])
nodeGroup[i] <- groupsdf[index[1], 2]
}
nodeList <-
cbind(nodeList,
nodeGroup)
progress <- shiny::Progress$new()
progress$set(message = "Generating your network...", value = 0)
# Close the progress when this reactive exits (even if there's an error)
on.exit(progress$close())
# Create a callback function to update progress.
# Each time this is called:
# - If `value` is NULL, it will move the progress bar 1/5 of the remaining
# distance. If non-NULL, it will set the progress to that value.
# - It also accepts optional detail text.
updateProgress <- function(value = NULL, detail = NULL) {
if (is.null(value)) {
value <- progress$getValue()
value <- value + (progress$getMax() - value) / 5
}
progress$set(value = value, detail = detail)
}
# Compute the new data, and pass in the updateProgress function so
# that it can update the progress indicator.
compute_data(updateProgress)
networkD3::forceNetwork(
Links = edgeList,
# data frame that contains info about edges
Nodes = nodeList,
# data frame that contains info about nodes
Source = "SourceID",
# ID of source node
Target = "TargetID",
# ID of target node
Value = "Weight",
# value from the edge list (data frame) that will be used to value/weight relationship amongst nodes
NodeID = "nName",
# value from the node list (data frame) that contains node
Group = "nodeGroup",
# value from the node list (data frame) that contains value we want to use for node color
fontSize = 25,
opacity = 0.85,
zoom = TRUE,
# ability to zoom when click on the node
opacityNoHover = 0.4 # opacity of labels when static
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I am sharing my fixed code in case it helps someone in the future. I basically just changed the top of the server code.
network.data <- eventReactive(input$makenet, {
Diet %>% filter(Predator_Scientific_Name == input$pred|Lowest_Taxonomic_Identification_Prey == input$prey
) %>% select(
paste(input$nodetax, "Predator", sep = "_"),
Class_Predator,
paste(input$nodetax, "Prey", sep = "_"),
Class_Prey,
input$dietmetric
) %>% rename("SourceName" = paste(input$nodetax, "Predator", sep = "_"),
"SourceClass" = Class_Predator,
"TargetName" = paste(input$nodetax, "Prey", sep = "_"),
"TargetClass" = Class_Prey,
"Weight" = input$dietmetric) %>% na.omit()
})
output$netplot <- renderForceNetwork( {
edgelist <- network.data()

Forms update output before submit button shiny R

My form automatically updates the output before I press the Submit button. I read the description of "Submit" button and it says "Forms that include a submit button do not automatically update their outputs when inputs change, rather they wait until the user explicitly clicks the submit button". I am not sure if there's anything wrong.
For your information, here is my code. Data is from UCI (adult data)
Server.R
library(shiny)
library(caret)
predictSalary <- function(input){
adultData <- read.table("adult.data", header = FALSE, sep = ",", strip.white = TRUE)
adultName <- read.csv("adult.name.csv", header = FALSE, sep = ",", stringsAsFactors = FALSE)
names(adultData) <- adultName[, 1]
#Only select several attributes
selected <- c("age", "education", "marital.status", "relationship", "sex", "hours.per.week", "salary")
#selected <- c("age", "hours.per.week", "salary")
adultData <- subset(adultData, select = selected)
#The data is big, we only take 20% for the training
trainIndex = createDataPartition(adultData$salary, p=0.20, list=FALSE)
training = adultData[ trainIndex, ]
set.seed(33833)
modFit <- train(salary ~ ., method = "rpart", data=training)
predict(modFit, newdata = input)
}
shinyServer(
function(input, output) {
dataInput <- reactive({
age <- input$age
edu <- as.factor(input$edu)
marritalstat <- input$marritalstat
relationship <- input$relationship
sex <- input$sex
hours <- input$hours
data.frame(age = age,
education = edu,
marital.status = marritalstat,
relationship = relationship,
sex = sex,
hours.per.week = hours)
# age <- input$age
# hours <- input$hours
# data.frame(age = age, hours.per.week = hours)
})
# dat <- c(input$age, input$edu, input$marritalstat,
# input$relationship, input$sex, input$hours)
output$prediction <- renderPrint({predictSalary(dataInput())})
}
)
Ui.R
library(shiny)
shinyUI(
pageWithSidebar(
# Application title
headerPanel("Salary prediction"),
sidebarPanel(
numericInput('age', 'Age', 40, min = 17, max = 90, step = 1),
selectInput('edu', 'Education',
c("Bachelors"="Bachelors",
"Some-college"="Some-college",
"11th"="11th",
"HS-grad"="HS-grad",
"Prof-school"="Prof-school",
"Assoc-acdm"="Assoc-acdm",
"Assoc-voc"="Assoc-voc",
"9th"="9th",
"7th-8th"="7th-8th",
"12th"="12th",
"Masters"="Masters",
"1st-4th"="1st-4th",
"10th"="10th",
"Doctorate"="Doctorate",
"5th-6th"="5th-6th",
"Preschool"="Preschool")),
radioButtons('marritalstat', 'Marrital Status',
c("Married-civ-spouse" = "Married-civ-spouse",
"Divorced" = "Divorced",
"Never-married" = "Never-married",
"Separated" = "Separated",
"Widowed" = "Widowed",
"Married-spouse-absent" = "Married-spouse-absent",
"Married-AF-spouse" = "Married-AF-spouse")),
radioButtons('relationship', 'Relationship',
c("Wife" = "Wife",
"Own-child" = "Own-child",
"Husband" = "Husband",
"Not-in-family" = "Not-in-family",
"Other-relative" = "Other-relative",
"Unmarried" = "Unmarried")),
radioButtons('sex', 'Sex', c("Male", "Female")),
numericInput('hours', 'Hours per week', 40, min = 1, max = 99, step = 1),
submitButton('Submit')
),
mainPanel(
h3('Results of prediction'),
h4('The predicted salary is '),
verbatimTextOutput("prediction"),
h3('Prediction of salary'),
p('The application is designed to predict whether somebodys salary is greater or smaller than 50k.
The data is extracted from the adult data, provided by UCI database. In order to predict a salary, users need to
provide information of the person whom they would like to make prediction on. After filling in necessary information,
users will press "Submit". The information includes:'),
p(' - Age: must be from 17 to 90'),
p(' - Education'),
p(' - Marital status'),
p(' - Relationship'),
p(' - Gender'),
p(' - Total work hours per week: must be from 1 to 99')
)
)
)
I found the solution by using actionButton in replacement of submitButton. However, I think that there must be an ideal solution with using submitButton.

Resources