Related
I tried to achieve when with a chosen split percentage, it returns the train set and then with a sampling method to resample train set and calculate its class freq and perc.
The error I got: object 'split.df' not found when I choose check box 'over'.
Should I use eventReactive or other syntax to achieve? The final return the table with either freq or perc should be dependent on 'split', 'sample' and dropdown 'freq' or 'perc'.
Here is portion that relates in ui:
sidebarLayout(
sidebarPanel(
h3("Train/test set"),
tags$br(),
selectInput(
"trainset",
"Select train component",
choices = list('freq'='freq', 'percentage'='perc'),
),
sliderInput(
"split",
label = "split percentage",
min = 0,
max = 1,
value = 0,
step = 0.1
),
h3("resampling train set"),
checkboxGroupInput('sample', label = "sampling method",
choices = list('original'='original','over'='over', 'under'='under', 'both'='both','ROSE'='ROSE'),
selected = list('original'='original'))
),
Here is a code relates for server:
split.df <- reactive({
index <- createDataPartition(df$class, p=input$split, list=FALSE)
Training_Data <- df[index,]
return(Training_Data)
})
train_set <- reactive({
if(input$sample == 'original')
Training_Data_class <- data.frame(class = split.df()$class)
return(Training_Data_class)
})
over_train_set <- reactive({
split.df <- split.df()
if(input$sample == 'over'){
over <- ovun.sample(class~., data = split.df, method = 'over')$data
Training_Data_class_over <- data.frame(class = over$class)
return(Training_Data_class_over)}
})
trainset_df <- reactive({
freq.df.train <- data.frame(table(train_set()))
colnames(freq.df.train) <- c('class', 'freq')
perc.df.train.=data.frame(prop.table(table(train_set()))*100)
colnames(perc.df.train) <- c('class','perc')
if(input$trainset == 'freq')
return(freq.df.train)
if(input$trainset == 'perc')
return(perc.df.train)
})
over_trainset_df <- reactive({
freq.df.train.over <- data.frame(table(over_train_set()))
colnames(freq.df.train.over) <- c('class', 'freq')
perc.df.train.over=data.frame(prop.table(table(over_train_set()))*100)
colnames(perc.df.train.over) <- c('class','perc')
if(input$trainset == 'freq')
return(freq.df.train.over)
if(input$trainset == 'perc')
return(perc.df.train.over)
})
output$trainsetdistr <- DT::renderDataTable({
if(input$sample == 'over'){
return(over_trainset_df())
}
if(input$sample == 'original'){
return(trainset_df())
}
}
)
I'm currently working on an Rshiny webapp to use for some simple classification. Currently, I've been working on creating a table that contains the CCR and MCR of both the CART and LDA methods on the data. My aim is then to highlight the column of the MCR and CCR of the best method (the method with the highest CCR... or lowest MCR). I have ran the code and viewed that it works correctly using the Viewer Pane. However, when I load the app, I obtain the error 'data' must be 2-dimensional (e.g. data frame or matrix).
Here is my code:
data <- read.csv("Fatality-task2.csv")
data$Rate <- as.factor(data$Rate)
library(shiny)
library(dplyr)
library(ggplot2)
library(markdown)
library(gtsummary)
library(ggdendro)
library(factoextra)
library(mclust)
library(cluster)
library(rpart)
library(rpart.plot)
library(DT)
#library(MASS)
glimpse(data)
#################################################################
ui <- fluidPage(
navbarPage("",
tabPanel("Data Exploration",
sidebarLayout(
sidebarPanel(
selectInput("variable",
"Variable",
colnames(data)),
selectInput("rate",
"Rate",
levels(data$Rate))
),
mainPanel(
tableOutput("table"),
plotOutput("plot")
)
)
),
tabPanel("Classification tools",
sidebarLayout(
sidebarPanel(
sliderInput("train.prop",
"Training data proportion",
min = 0.4,
max = 0.8,
step = 0.1,
value = 0.6),
radioButtons("prune",
"Pruning option",
choices = c("view pruned tree",
"view unpruned tree"))
),
mainPanel(
DTOutput("table2"),
plotOutput("plot2")
)
)
)
)
)
#################################################################
server <- function(input, output) {
output$table <- renderTable({
req(input$variable,input$rate)
data <- data %>%
filter(Rate == input$rate) %>%
dplyr::select(input$variable) %>%
summary() %>%
as.data.frame() %>%
tidyr::separate(Freq, c("Stat", "Value"), sep=":") %>%
tidyr::pivot_wider(names_from =Stat, values_from = Value)
data <- data[, -c(1,2)]
})
output$plot <- renderPlot({
req(input$variable)
if (input$variable == "jaild" | input$variable == "Rate"){
ggplot(data, aes(x = Rate, fill = .data[[as.name(input$variable)]])) +
geom_bar(position = "dodge", width = 0.7) +
if (input$variable == "Rate"){
theme(legend.position = "none")
}
} else {
ggplot(data, aes(x = Rate, y = .data[[as.name(input$variable)]], fill = Rate)) +
geom_boxplot() +
theme(legend.position = "none")
}
})
output$plot2 <- renderPlot({
req(input$train.prop,input$prune)
set.seed(1234)
n <- nrow(data)
ind1 <- sample(c(1:n), round(n*as.numeric(input$train.prop)))
ind2 <- sample(c(1:n)[-ind1], length(c(1:n)[-ind1]))
train.data <- data[ind1,]
valid.data <- data[ind2,]
fit.tree <- rpart(Rate~., data = train.data, method = "class")
ptree <- prune(fit.tree, cp = fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"])
if (input$prune == "view pruned tree"){
rpart.plot(ptree, uniform =TRUE)
} else {
rpart.plot(fit.tree)
}
})
output$table2 <- DT::renderDT({
library(MASS)
set.seed(1234)
n <- nrow(data)
ind1 <- sample(c(1:n), round(n*0.6))
#ind2 <- sample(c(1:n)[-ind1], length(c(1:n)[-ind1]))
ind2 <- setdiff(c(1:n), ind1)
train.data <- data[ind1,]
valid.data <- data[ind2,]
#################################
### fit cart model
fit.tree <- rpart(Rate~., data = train.data, method = "class")
### prune the tree
ptree <- prune(fit.tree, cp = fit.tree$cptable[which.min(fit.tree$cptable[,"xerror"]),"CP"])
### predict using the validation data on the pruned tree
pred <- predict(ptree, newdata = valid.data[,-6], type = "class")
### lda
#lda.model <- lda(train.data[,-6], train.data[,6])
lda.model <- lda(Rate~., data = train.data)
lda.pred <- predict(lda.model, newdata = valid.data[,-6])
### create a classification table
length(lda.model)
x <- pred == valid.data[,6]
CCR <- length(x[x == TRUE])/nrow(valid.data)
MCR <- 1 - CCR
CR <- c(CCR, MCR)
z <- lda.pred$class == valid.data[,6]
lda.CCR <- length(z[z == TRUE])/nrow(valid.data)
lda.MCR <- 1 - lda.CCR
lda.CR <- c(lda.CCR, lda.MCR)
y <- cbind(CR, lda.CR)
y <- as.data.frame(y)
colnames(y) <- c("CART", "LDA")
rownames(y) <- c("CCR", "MCR")
#y
DT::datatable(y, options=list(dom = "t")) %>%
formatRound(columns = c(1,2), digits = 6) %>%
formatStyle(columns = colnames(y[which.max(y[1,])]), background = "green")
#colnames(y[1])
#colnames(y[which.max(y[1,])])
},
rownames = TRUE)
}
?formatStyle
?formatRound()
#################################################################
shinyApp(ui, server)
and here is some of my data:
"beertax","jaild","vmiles","unrate","perinc","Rate"
1.53937947750092,"no",7.23388720703125,14.3999996185303,10544.15234375,1
1.78899073600769,"no",7.83634765625,13.6999998092651,10732.7978515625,1
1.71428561210632,"no",8.262990234375,11.1000003814697,11108.791015625,1
1.65254235267639,"no",8.7269169921875,8.89999961853027,11332.626953125,1
1.60990703105927,"no",8.952853515625,9.80000019073486,11661.5068359375,1
1.55999994277954,"no",9.1663017578125,7.80000019073486,11944,1
1.50144362449646,"no",9.6743232421875,7.19999980926514,12368.6240234375,1
0.214797139167786,"yes",6.81015673828125,9.89999961853027,12309.0693359375,1
0.206422030925751,"yes",6.58749462890625,9.10000038146973,12693.8076171875,1
0.296703308820724,"yes",6.70997021484375,5,13265.93359375,1
0.381355941295624,"yes",6.7712626953125,6.5,13726.6953125,1
0.371517032384872,"yes",8.1290078125,6.90000009536743,14107.3271484375,1
0.360000014305115,"yes",9.370654296875,6.19999980926514,14241,1
0.346487015485764,"yes",9.815720703125,6.30000019073486,14408.0849609375,1
0.650358021259308,"no",7.20850048828125,9.80000019073486,10267.302734375,1
0.67545872926712,"no",7.1759169921875,10.1000003814697,10433.486328125,1
0.598901093006134,"no",7.08481982421875,8.89999961853027,10916.4833984375,1
0.577330529689789,"no",7.25391796875,8.69999980926514,11149.3642578125,1
0.562435507774353,"no",7.4689990234375,8.69999980926514,11399.380859375,1
0.545000016689301,"no",7.66583056640625,8.10000038146973,11537,1
0.52454286813736,"no",8.02462548828125,7.69999980926514,11760.3466796875,1
0.107398569583893,"no",6.8586767578125,9.89999961853027,15797.1357421875,0
0.103211015462875,"no",7.21629150390625,9.69999980926514,15970.18359375,0
0.0989011004567146,"no",7.61917578125,7.80000019073486,16590.109375,0
0.0953389853239059,"no",7.87406689453125,7.19999980926514,16985.169921875,0
0.0928792580962181,"no",8.03491015625,6.69999980926514,17356.037109375,0
0.0900000035762787,"no",8.18063330078125,5.80000019073486,17846,0
0.0866217538714409,"no",8.531990234375,5.30000019073486,18049.0859375,0
0.214797139167786,"no",7.742841796875,7.69999980926514,15082.3388671875,1
0.206422030925751,"no",7.65606298828125,6.59999990463257,15131.880859375,1
0.197802200913429,"no",7.7078525390625,5.59999990463257,15486.8134765625,0
0.190677970647812,"no",8.09220947265625,5.90000009536743,15569.9150390625,0
0.185758516192436,"no",8.13137451171875,7.40000009536743,15616.0986328125,0
0.180000007152557,"no",8.18202783203125,7.69999980926514,15605,0
0.173243507742882,"no",8.3807685546875,6.40000009536743,15845.04296875,0
0.224343672394753,"no",6.4400537109375,6.90000009536743,17255.369140625,0
0.233563080430031,"no",6.57004296875,6,17744.265625,0
0.248010993003845,"no",6.68019287109375,4.59999990463257,18760.439453125,0
0.239078402519226,"yes",6.97921484375,4.90000009536743,19312.5,0
I know the code works properly - I just want it to be able to run properly on the app. Please help!
Following on from this post I am trying to find a way to search multiple items my datatable with spaces rather than pipes and was able to implement this as per the previous post. Implementing this code into the following example works well:
library(shiny)
library(DT)
library(shinythemes)
## ------------------------------------ functions
## JS for searching with spaces between items instead of pipes
callback <- '
$("div.search").append($("#mySearch"));
$("#mySearch").on("keyup redraw", function(){
var splits = $("#mySearch").val().split(" ").filter(function(x){return x !=="";})
var searchString = "(" + splits.join("|") + ")";
table.search(searchString, true).draw(true);
});
'
## css styling
CSS <- function(values, colors){
template <- "
.option[data-value=%s], .item[data-value=%s]{
background: %s !important;
color: white !important;
}"
paste0(
apply(cbind(values, colors), 1, function(vc){
sprintf(template, vc[1], vc[1], vc[2])
}),
collapse = "\n"
)
}
## points to highlight
highlightOnPlot <- function(coords, fd, myfoi, labels = FALSE) {
.data <- coords
points(.data[myfoi, 1], .data[myfoi, 2], col = "white",
pch = 21, cex = 1, lwd = 1.3)
if (labels) {
text(.data[myfoi, 1], .data[myfoi, 2], myfoi, pos = 3, font = 2, cex = 1.2)
}
}
## ------------------------------------ data
## create dataset from iris
data(iris)
object <- iris
rownames(object) <- 1:nrow(object)
m <- object$Species
um <- levels(factor(m))
M <- matrix(0, nrow = nrow(object), ncol = length(um))
rownames(M) <- rownames(object)
colnames(M) <- um
for (j in um) M[which(j == m), j] <- 1
fd <- data.frame(markers = iris$Species, M)
## generate pca
coords <- prcomp(object[,1:4])$x[, 1:2]
rownames(coords) <- rownames(M)
## ------------------------------------ app settings
pmsel <- 1:ncol(M)
profs <- iris[, 1:4]
feats <- toSel <- c(1:ncol(fd))
idxDT <- numeric()
namesIdxDT <- character()
cols <- c("#E41A1C", "#377EB8", "#238B45", "#FF7F00")
fcol <- "markers"
css <- CSS(colnames(M), cols[seq(colnames(M))])
## ------------------------------------ UI
ui <-
shinyUI(
tagList(
navbarPage(
theme = shinytheme("flatly"), "flatly theme",
tabPanel("",
sidebarLayout(
## sidebarPanel
sidebarPanel(
tags$head(tags$style(HTML(css))),
selectizeInput("markers", "Labels",
choices = colnames(M),
multiple = TRUE,
selected = colnames(M)[pmsel])),
## mainPanel
mainPanel(
plotOutput("pca")
) # end of mainPanel
), # end of sidebarLayout
## ------Datatable-----
tags$head(tags$style(HTML(".search {float: right;}"))),
br(),
tags$input(type = "text", id = "mySearch", placeholder = "Search"),
DT::dataTableOutput("fDataTable")
) # end of tabPanel
)))
## ------------------------------------ SERVER
server <-
shinyServer(
function(input, output, session) {
## Get coords for data according to selectized class(es)
mrkSel <- reactive({lapply(input$markers, function(z) which(M[, z] == 1))})
## Update colours according to selected classes
myCols <- reactive({cols[sapply(input$markers, function(z)
which(colnames(M) == z))]})
## PCA plot
output$pca <- renderPlot({
plot(x = coords[,1], y = coords[,2])
if (!is.null(input$markers)) {
for (i in 1:length(input$markers))
points(coords[mrkSel()[[i]], ], col = myCols()[i], pch = 19)
}
})
## Feature data table
output$fDataTable <- DT::renderDataTable({
dtdata <- fd
## display datatable
DT::datatable(data = dtdata,
rownames = TRUE,
options = list(
search = list(regex = TRUE,
caseInsensitive = TRUE),
dom = "l<'search'>rtip"
),
selection = list(mode = 'multiple', selected = toSel),
callback = JS(callback))
})
})
shinyApp(ui, server)
I have quite a complicated app that uses brushing and zooming on multiple plots and have tried to simplify it here into a reproducible example. If I add in the brushing and zooming features, as per the below code, I lose the search box of my DT table.
Can anyone please advise how to rectify this? (Apologies this is still code heavy but leaving out the brushing and zooming I can't reproduce the error.)
Many thanks in advance.
library(shiny)
library(DT)
library(shinythemes)
## ------------------------------------ functions
## JS for searching with spaces between items instead of pipes
callback <- '
$("div.search").append($("#mySearch"));
$("#mySearch").on("keyup redraw", function(){
var splits = $("#mySearch").val().split(" ").filter(function(x){return x !=="";})
var searchString = "(" + splits.join("|") + ")";
table.search(searchString, true).draw(true);
});
'
## css styling
CSS <- function(values, colors){
template <- "
.option[data-value=%s], .item[data-value=%s]{
background: %s !important;
color: white !important;
}"
paste0(
apply(cbind(values, colors), 1, function(vc){
sprintf(template, vc[1], vc[1], vc[2])
}),
collapse = "\n"
)
}
## points to highlight
highlightOnPlot <- function(coords, fd, myfoi, labels = FALSE) {
.data <- coords
points(.data[myfoi, 1], .data[myfoi, 2], col = "white",
pch = 21, cex = 1, lwd = 1.3)
if (labels) {
text(.data[myfoi, 1], .data[myfoi, 2], myfoi, pos = 3, font = 2, cex = 1.2)
}
}
## ------------------------------------ data
## create dataset from iris
data(iris)
object <- iris
rownames(object) <- 1:nrow(object)
m <- object$Species
um <- levels(factor(m))
M <- matrix(0, nrow = nrow(object), ncol = length(um))
rownames(M) <- rownames(object)
colnames(M) <- um
for (j in um) M[which(j == m), j] <- 1
fd <- data.frame(markers = iris$Species, M)
## generate pca
coords <- prcomp(object[,1:4])$x[, 1:2]
rownames(coords) <- rownames(M)
## ------------------------------------ app settings
pmsel <- 1:ncol(M)
profs <- iris[, 1:4]
feats <- toSel <- c(1:ncol(fd))
idxDT <- numeric()
namesIdxDT <- character()
cols <- c("#E41A1C", "#377EB8", "#238B45", "#FF7F00")
fcol <- "markers"
css <- CSS(colnames(M), cols[seq(colnames(M))])
## ------------------------------------ UI
ui <-
shinyUI(
tagList(
navbarPage(
theme = shinytheme("flatly"), "flatly theme",
tabPanel("",
sidebarLayout(
## sidebarPanel
sidebarPanel(
tags$head(tags$style(HTML(css))),
selectizeInput("markers", "Labels",
choices = colnames(M),
multiple = TRUE,
selected = colnames(M)[pmsel]),
br(),
actionButton("resetButton", "Zoom/reset plot"),
br(),
actionButton("clear", "Clear selection"),
width = 3),
## mainPanel
mainPanel(
plotOutput("pca",
dblclick = "dblClick",
brush = brushOpts(id = "pcaBrush", resetOnNew = TRUE))
) # end of mainPanel
), # end of sidebarLayout
## ------Datatable-----
tags$head(tags$style(HTML(".search {float: right;}"))),
br(),
tags$input(type = "text", id = "mySearch", placeholder = "Search"),
DT::dataTableOutput("fDataTable")
) # end of tabPanel
)))
## ------------------------------------ SERVER
server <-
shinyServer(
function(input, output, session) {
## settings for brushing on the plot
ranges <- reactiveValues(x = NULL, y = NULL)
brushBounds <- reactiveValues(i = try(coords[, 1] >= min(coords[, 1]) &
coords[, 1] <= max(coords[, 1])),
j = try(coords[, 2] >= min(coords[, 2]) &
coords[, 2] <= max(coords[, 2])))
resetLabels <- reactiveValues(logical = FALSE)
## Get coords for data according to selectized class(es)
mrkSel <- reactive({lapply(input$markers, function(z) which(M[, z] == 1))})
## Update colours according to selected classes
myCols <- reactive({cols[sapply(input$markers, function(z)
which(colnames(M) == z))]})
## PCA plot
output$pca <- renderPlot({
plot(x = coords[,1], y = coords[,2],
xlim = ranges$x, ylim = ranges$y)
if (!is.null(input$markers)) {
for (i in 1:length(input$markers))
points(coords[mrkSel()[[i]], ], col = myCols()[i], pch = 19)
}
## highlight point on plot by selecting item in table
idxDT <<- feats[input$fDataTable_rows_selected]
if (resetLabels$logical) idxDT <<- numeric() ## If TRUE labels are cleared
namesIdxDT <<- names(idxDT)
if (length(idxDT)) {
highlightOnPlot(coords, fd, namesIdxDT)
highlightOnPlot(coords, fd, namesIdxDT, labels = TRUE)
}
resetLabels$logical <- FALSE
})
## Feature data table
output$fDataTable <- DT::renderDataTable({
## Double clicking to identify point
feats <<- which(brushBounds$i & brushBounds$j)
if (!is.null(input$dblClick)) {
dist <- apply(coords, 1, function(z) sqrt((input$dblClick$x - z[1])^2
+ (input$dblClick$y - z[2])^2))
idxPlot <- which(dist == min(dist))
if (idxPlot %in% idxDT) { ## 1--is it already clicked?
setsel <- setdiff(names(idxDT), names(idxPlot)) ## Yes, remove it from table
idxDT <<- idxDT[setsel]
} else { ## 2--new click?
idxDT <<- c(idxDT, idxPlot) ## Yes, highlight it to table
}
}
namesIdxDT <<- names(idxDT)
toSel <- match(namesIdxDT, rownames(fd)[brushBounds$i & brushBounds$j])
if (resetLabels$logical) toSel <- numeric()
dtdata <- fd
dtdata <- dtdata[brushBounds$i & brushBounds$j, ]
## display datatable
DT::datatable(data = dtdata,
rownames = TRUE,
options = list(
search = list(regex = TRUE,
caseInsensitive = TRUE),
dom = "l<'search'>rtip"
),
selection = list(mode = 'multiple', selected = toSel),
callback = JS(callback))
})
## When a the reset button is clicked check to see is there is a brush on
## the plot, if yes zoom, if not reset the plot.
observeEvent(input$resetButton, {
brush <- input$pcaBrush
if (!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
brushBounds$i <- coords[, 1] >= brush$xmin & coords[, 1] <= brush$xmax
brushBounds$j <- coords[, 2] >= brush$ymin & coords[, 2] <= brush$ymax
} else {
ranges$x <- NULL
ranges$y <- NULL
brushBounds$i <- try(coords[, 1] >= min(coords[, 1])
& coords[, 1] <= max(coords[, 1]))
brushBounds$j <- try(coords[, 2] >= min(coords[, 2])
& coords[, 2] <= max(coords[, 2]))
}
})
## Clear indices and reset clicked selection
observeEvent(input$clear, {resetLabels$logical <- TRUE})
})
shinyApp(ui, server)
SessionInfo
> sessionInfo()
R version 3.6.3 (2020-02-29)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS High Sierra 10.13.6
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] shinythemes_1.1.2 DT_0.13 shiny_1.4.0.2
loaded via a namespace (and not attached):
[1] Rcpp_1.0.4.6 crayon_1.3.4 digest_0.6.25 later_1.0.0 mime_0.9 R6_2.4.1
[7] jsonlite_1.6.1 xtable_1.8-4 magrittr_1.5 rlang_0.4.5 rstudioapi_0.11 promises_1.1.0
[13] tools_3.6.3 htmlwidgets_1.5.1 crosstalk_1.1.0.1 rsconnect_0.8.16 yaml_2.2.1 httpuv_1.5.2
[19] fastmap_1.0.1 compiler_3.6.3 htmltools_0.4.0
Thanks again.
When you play with the brushing/zooming, the renderDT reacts. I believe this destroys the previous table and also the text input mySearch because it is included in the datatable.
I have not tried with a reactive datatable, but I think the following code should work. The text input mySearch is created in the callback, so it should be recreated when a new table is created. So remove the tags$input as well as the CSS, because I set the CSS property float in the callback.
library(shiny)
library(DT)
callback <- '
var x = document.createElement("INPUT");
x.setAttribute("type", "text");
x.setAttribute("id", "mySearch");
x.setAttribute("placeholder", "Search");
x.style.float = "right";
$("div.search").append($(x));
$("#mySearch").on("keyup redraw", function(){
var splits = $("#mySearch").val().split(" ").filter(function(x){return x !=="";})
var searchString = "(" + splits.join("|") + ")";
table.search(searchString, true).draw(true);
});
'
ui <- fluidPage(
#tags$head(tags$style(HTML(".search {float: right;}"))), --- REMOVE THAT
br(),
DTOutput("dtable")
)
server <- function(input, output){
output[["dtable"]] <- renderDT({
datatable(
iris[c(1,2,51,52,101,102),],
options = list(
dom = "l<'search'>rtip"
),
callback = JS(callback)
)
}, server = FALSE)
}
shinyApp(ui, server)
I am writing a small shiny app to interactively display filtered data. I want to animate the transition in the data and in the axis bounds. No matter what I do I can't get the axis bounds to animate smoothly. Does anyone know how to do this?
# herd testing shiny app
version <- "v0.2"
library(shiny)
library(shinyjs)
library(readr)
library(dplyr)
library(stringr)
library(plotly)
library(purrr)
# notin function
"%notin%" <- function(x,y)!("%in%"(x,y))
# avoid as.numeric coercion warnings
as_numeric <- function(x, default=NA_real_){
suppressWarnings(if_else(is.na(as.numeric(x)), default, as.numeric(x)))
}
as_integer <- function(x, default=NA_integer_){
suppressWarnings(if_else(is.na(as.integer(x)), default, as.integer(x)))
}
# range including zero and handling NA
zrange <- function(x){
c(min(c(0, x), na.rm=TRUE), max(c(0, x), na.rm=TRUE))
}
# test data for reprex
data <- data.frame(
herd = rep(LETTERS, each=10),
year = rep(2010:2019, times=26),
count = sample(c(NA, 0:10), 260, TRUE),
percent = sample(c(NA, 0:10), 260, TRUE)/100
)
herds <- unique(data$herd)
herds1 <- sample(herds, 1)
# some colours
zzgreen <- "#69BE28"
zzblue <- "#009AA6"
ui <- fluidPage(
cat("run ui function\n"),
theme = shinythemes::shinytheme("spacelab"), # kinda similar to DairyNZ and plotly
align="center",
# https://www.w3schools.com/css/default.asp
fluidRow(
column(3,
strong("Select Herd:", style="font-size: 14px;"),
br(""),
textInput("herd", label="Enter Herd Code:", value=herds1)
),
column(9,
align="left",
strong("Herd Tests:", style="font-size: 14px;"),
plotlyOutput("count_plot", height="auto"),
strong("DNA Verified:", style="font-size: 14px;"),
plotlyOutput("perc_plot", height="auto")
)
),
fluidRow(
align="right",
em(version)
)
) # fluidPage
server <- function(input, output, session){
cat("run server function\n")
my <- reactiveValues(
herd = herds1,
frame = 0,
data = filter(data, herd==herds1),
speed = 500,
plist = list()
) # reactiveValues
observeEvent(input$herd, {
req(input$herd %in% herds)
my$herd <- input$herd
my$frame <- my$frame + 1
cat("new herd", input$herd, "new frame", my$frame, "calc plist\n")
# filter data
my$data <- data %>%
filter(herd==my$herd)
print(my$data)
# get existing list
pl <- my$plist
# herd test count data
pl[[1]] <- list(x=my$data$year,
y=my$data$count,
frame=my$frame,
name = "Herd Test Count",
showlegend=TRUE,
color=I(zzblue),
type="scatter",
mode="lines+markers")
# percent DNA verified data
pl[[2]] <- list(x=my$data$year,
y=my$data$percent*100,
frame=my$frame,
name = "Percent Verified",
showlegend=TRUE,
color=I(zzgreen),
type="scatter",
mode="lines+markers")
# https://plot.ly/r/multiple-axes/
# herd test count axis
pl[[3]] <- list(
title = list(text=my$herd),
xaxis=list(title=list(text="<b>Year</b>"),
tick0=min(my$data$year),
dtick=1,
range=range(my$data$year),
zeroline=FALSE,
type="linear"),
yaxis=list(title=list(text="<b>Herd Test Count</b>"),
zeroline=TRUE,
range=zrange(my$data$count),
type="linear"))
cat("range", zrange(my$data$count), "\n")
# percent DNA verified axis
pl[[4]] <- list(
xaxis=list(title=list(text="<b>Year</b>"),
tick0=min(my$data$year),
dtick=1,
range=range(my$data$year),
zeroline=FALSE,
type="linear"),
yaxis=list(title=list(text="<b>Percent Verified</b>"),
zeroline=TRUE,
range=zrange(my$data$percent*100),
type="linear"))
cat("range", zrange(my$data$percent*100), "\n")
# animation options
pl[[5]] <- list(frame=my$speed,
transition=my$speed,
redraw=FALSE,
mode="next")
pl[[6]] <- list(frame=0,
transition=0,
redraw=FALSE,
mode="next")
my$plist <- pl
})
output$count_plot <- renderPlotly({
cat("initial count_plot\n")
isolate({
# https://stackoverflow.com/questions/39019212/suppress-plotly-warnings-in-shiny-app
store_warn <- getOption("warn"); options(warn=-1)
pl <- my$plist
p <- plot_ly()
p <- do.call(add_trace, prepend(pl[[1]], list(p)))
p <- do.call(layout, prepend(pl[[3]], list(p)))
p <- do.call(animation_opts, prepend(pl[[5]], list(p)))
# restore warnings, delayed so plot is completed
shinyjs::delay(100, options(warn=store_warn))
p
})
}) # renderPlotly
count_plot_proxy <- plotlyProxy("count_plot", session=session)
output$perc_plot <- renderPlotly({
cat("initial perc_plot\n")
isolate({
# https://stackoverflow.com/questions/39019212/suppress-plotly-warnings-in-shiny-app
store_warn <- getOption("warn"); options(warn=-1)
pl <- my$plist
p <- plot_ly()
p <- do.call(add_trace, prepend(pl[[2]], list(p)))
p <- do.call(layout, prepend(pl[[4]], list(p)))
p <- do.call(animation_opts, prepend(pl[[5]], list(p)))
# restore warnings, delayed so plot is completed
shinyjs::delay(100, options(warn=store_warn))
p
})
}) # renderPlotly
perc_plot_proxy <- plotlyProxy("perc_plot", session=session)
observeEvent(my$herd, {
cat("new herd", my$herd, "update plots\n")
pl <- my$plist
# plotlyProxyInvoke(count_plot_proxy, "animate",
# list(
# name = as.character(my$frame),
# layout = pl[[3]]
# ),
# pl[[5]]
# )
plotlyProxyInvoke(count_plot_proxy, "animate",
list(
name = as.character(my$frame),
data = pl[1],
traces = as.list(as.integer(0)),
layout = pl[[3]]
),
pl[[5]]
)
# plotlyProxyInvoke(count_plot_proxy, "relayout",
# update = pl[3])
# plotlyProxyInvoke(perc_plot_proxy, "animate",
# list(
# name = as.character(my$frame),
# layout = pl[[4]]
# ),
# pl[[5]]
# )
plotlyProxyInvoke(perc_plot_proxy, "animate",
list(
name = as.character(my$frame),
data = pl[2],
traces = as.list(as.integer(0)),
layout = pl[[4]]
),
pl[[5]]
)
# plotlyProxyInvoke(count_plot_proxy, "relayout",
# update = pl[3])
}) # observeEvent
} # server
# run app
shinyApp(ui, server)
Thanks so much for your help, I am adding extra text here so that SO allows me to post this.
Hey I am trying to build a shiny app for the purpose of calculating per cent chance of defaulting and I thought I fixed all my issues until I hit
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
but whenever I try to build something reactive I get
Error in RET#get_where(newdata = newdata, mincriterion = mincriterion) :
object 'loanfilev3' not found
I've looked over stackoverflow and tutorials and none seem to really help
Here is my UI and Server code for the first error, if someone could please highlight my issue that would be greatly appreciated.
UI:
library(shiny)
shinyUI(fluidPage(
titlePanel("Tabsets"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select the random distribution type ----
numericInput("loan_amnt",
"Loan Amount:",
value = 5000,
min = 0,
max = NA),
numericInput("int_rate",
"Interest Rate:",
value = 10.5,
min = 0,
max = NA),
selectInput("term",
"Loan Term:",
c("36 months" = " 36 months",
"60 months" = " 60 months")),
numericInput("installment",
"Installment:",
value = 100,
min = 0,
max = NA),
textInput("grade", "Grade:", "B"),
textInput("emp_length", "Employment Length:", "5 years"),
numericInput("annual_inc",
"Annual Income:",
value = 40000,
min = 0,
max = NA),
numericInput("dti",
"Debt to Income Ratio:",
value = 5.4,
min = NA,
max = NA),
textInput("sub_grade", "SubGrade:", "B2"),
textInput("verification_status", "Verification Status:", "Verified"),
textInput("home_ownership", "Home Ownership:", "RENT"),
radioButtons("pymnt_plan", "Payment Plan:",
c("Yes" = "y",
"No" = "n"))
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs",
tabPanel("Decision Tree", verbatimTextOutput("ct")),
tabPanel("Generlized Linear Model", verbatimTextOutput("dl")),
tabPanel("K-Nearest Neighbour", verbatimTextOutput("kn"))
)
)
)
)
)
Server:
library(shiny)
library(pscl)
library(ROCR)
library(plyr)
library(dplyr)
library(ggplot2)
library(pROC)
library(caret)
library(e1071)
library(RMySQL)
library(reshape2)
USER <- 'inft216'
PASSWORD <- 'rosemary'
HOST <- 'bruce3.dc.bond.edu.au'
DBNAME <- 'inft216'
db <- dbConnect(MySQL(), user = USER, password = PASSWORD, host = HOST, dbname = DBNAME)
loanfile <- dbGetQuery(db, statement = "select * from lendingClub;")
dbDisconnect(db)
library(party)
colnames(loanfile) = tolower(colnames(loanfile))
bad_indicators = c("Charged Off",
"Default",
"Does not meet the credit policy. Status:Charged Off",
"Default Receiver",
"Late (16-30 days)",
"Late (31-120 days)")
loanfile$default = ifelse(loanfile$loan_status %in% bad_indicators, 1,
ifelse(loanfile$loan_status=="", NA, 0))
loanfile$loan_status = as.factor(loanfile$default)
loanfilev2 = dplyr::select(.data = loanfile,loan_status,loan_amnt,int_rate,term,installment,grade,emp_length,annual_inc,dti,sub_grade,verification_status,home_ownership,pymnt_plan)
loanfilev2$grade = as.factor(loanfilev2$grade)
loanfilev2$sub_grade <- as.factor(loanfilev2$sub_grade)
loanfilev2$term <- as.factor(loanfilev2$term)
loanfilev2$emp_length <- as.factor(loanfilev2$emp_length)
loanfilev2$verification_status <- as.factor(loanfilev2$verification_status)
loanfilev2$home_ownership <- as.factor(loanfilev2$home_ownership)
loanfilev2$pymnt_plan <- as.factor(loanfilev2$pymnt_plan)
loanfilev2$loan_status <- as.factor(loanfilev2$loan_status)
loanfilev2$grade <- as.numeric(loanfilev2$grade)
loanfilev2$sub_grade <- as.numeric(loanfilev2$sub_grade)
loanfilev2$term <- as.numeric(loanfilev2$term)
loanfilev2$emp_length <- as.numeric(loanfilev2$emp_length)
loanfilev2$verification_status <- as.numeric(loanfilev2$verification_status)
loanfilev2 <- loanfilev2[complete.cases(loanfilev2),]
set.seed(69)
train_index <- sample(seq_len(nrow(loanfilev2)), size = 5000)
TrainData<- loanfilev2[train_index, ]
ct = ctree(loan_status ~ ., data = TrainData)
dl <- glm(formula = loan_status ~ .,data = loanfilev2, family = binomial)
kn <- train(form = loan_status ~.,data = TrainData, method = 'knn')
shinyServer(function(input, output) {
loan_status <- c(0)
loan_amnt <- input$loan_amnt
int_rate <- input$int_rate
term <- input$term
installment <- input$installment
grade <- input$grade
emp_length <- input$emp_length
annual_inc <- input$annual_inc
dti <- input$dti
sub_grade <- input$sub_grade
verification_status <- input$verification_status
home_ownership <- input$home_ownership
pymnt_plan <- input$pymnt_plan
temp2 <- cbind(loan_status, loan_amnt, int_rate, term, installment, grade, emp_length, annual_inc, dti, sub_grade, verification_status, home_ownership, pymnt_plan)
loanfilev3 = dplyr::select(.data = loanfile,loan_status,loan_amnt,int_rate,term,installment,grade,emp_length,annual_inc,dti,sub_grade,verification_status,home_ownership,pymnt_plan)
loanfilev3 = rbind(loanfilev3, temp2, deparse.level = 0)
loanfilev3$grade = as.factor(loanfilev3$grade)
loanfilev3$sub_grade <- as.factor(loanfilev3$sub_grade)
loanfilev3$term <- as.factor(loanfilev3$term)
loanfilev3$emp_length <- as.factor(loanfilev3$emp_length)
loanfilev3$verification_status <- as.factor(loanfilev3$verification_status)
loanfilev3$home_ownership <- as.factor(loanfilev3$home_ownership)
loanfilev3$pymnt_plan <- as.factor(loanfilev3$pymnt_plan)
loanfilev3$loan_status <- as.factor(loanfilev3$loan_status)
loanfilev3$grade <- as.numeric(loanfilev3$grade)
loanfilev3$sub_grade <- as.numeric(loanfilev3$sub_grade)
loanfilev3$term <- as.numeric(loanfilev2$term)
loanfilev3$emp_length <- as.numeric(loanfilev3$emp_length)
loanfilev3$verification_status <- as.numeric(loanfilev3$verification_status)
loanfilev3 <- loanfilev3[complete.cases(loanfilev3),]
prediction1 = c(predict(object = ct, newdata = loanfilev3[886508], type = "prob"))
output$ct <- renderPrint({
as.data.frame(prediction1)[2,]*100
})
})
All input bindings (input$whatever) need to be used in reactive context for example: inside reactive() or observe or renderXXX etc. In your case you are doing stuff like loan_amnt <- input$loan_amnt outside of reactive context and that's what the error is about. See my update below. I have added your prediction model to an eventReactive that is triggered by some action button input$predict.
# add this button somewhere in your ui.R -
actionButton("predict", "Predict!")
update to server.R -
shinyServer(function(input, output) {
prediction <- eventReactive(input$predict, {
loan_status <- c(0)
loan_amnt <- input$loan_amnt
int_rate <- input$int_rate
term <- input$term
installment <- input$installment
grade <- input$grade
emp_length <- input$emp_length
annual_inc <- input$annual_inc
dti <- input$dti
sub_grade <- input$sub_grade
verification_status <- input$verification_status
home_ownership <- input$home_ownership
pymnt_plan <- input$pymnt_plan
temp2 <- cbind(loan_status, loan_amnt, int_rate, term, installment, grade, emp_length, annual_inc, dti, sub_grade, verification_status, home_ownership, pymnt_plan)
loanfilev3 = dplyr::select(.data = loanfile,loan_status,loan_amnt,int_rate,term,installment,grade,emp_length,annual_inc,dti,sub_grade,verification_status,home_ownership,pymnt_plan)
loanfilev3 = rbind(loanfilev3, temp2, deparse.level = 0)
loanfilev3$grade = as.factor(loanfilev3$grade)
loanfilev3$sub_grade <- as.factor(loanfilev3$sub_grade)
loanfilev3$term <- as.factor(loanfilev3$term)
loanfilev3$emp_length <- as.factor(loanfilev3$emp_length)
loanfilev3$verification_status <- as.factor(loanfilev3$verification_status)
loanfilev3$home_ownership <- as.factor(loanfilev3$home_ownership)
loanfilev3$pymnt_plan <- as.factor(loanfilev3$pymnt_plan)
loanfilev3$loan_status <- as.factor(loanfilev3$loan_status)
loanfilev3$grade <- as.numeric(loanfilev3$grade)
loanfilev3$sub_grade <- as.numeric(loanfilev3$sub_grade)
loanfilev3$term <- as.numeric(loanfilev2$term)
loanfilev3$emp_length <- as.numeric(loanfilev3$emp_length)
loanfilev3$verification_status <- as.numeric(loanfilev3$verification_status)
loanfilev3 <- loanfilev3[complete.cases(loanfilev3),]
predict(object = ct, newdata = loanfilev3[886508], type = "prob"))
})
output$ct <- renderPrint({
as.data.frame(prediction())[2,]*100
})
})