Initial scaling in shiny - r

I've got a problem using the shiny package in R. I'm trying to insert income. debt and bonus entered in the slider that I've built into the original data set so the algorithm can scale i.e. normalise the data to make the calculation. Right now I can only make the calculation as-is i.e. when you enter the data it calculates it however, as I indicated, I want the data entered to go back into the original data set so I can scale it before making the calculation. I have the below code for the shiny package.
library(shiny)
shinyUI(fluidPage(
headerPanel("Calculating fwbs"),
sidebarPanel(
sliderInput("Income", "Please Select Income: ", min=0, max=5000,
value=2500, step=100),
sliderInput("Debt", "Please Select Debt: ", min = 0, max=2500,
value=1250, step = 100),
sliderInput("Bonus", "Have you received any bonus: ", min=0, max= 1000,
value=500, step =100)
),
mainPanel(
textOutput("fwbi")
)
))
shinyServer(function(input, output, session){
output$fwbi <- renderText({
income2<- input$Income
debt2<- input$Debt
bonus2<- input$Bonus
paste("Your fwbi is: ", income2 + debt2 + bonus2)
})
})
Many thanks

If you want to be able to add an arbitrary number of rows to the original data, you can use a reactiveValues list:
Dframe <- data.frame(income = rnorm(5),
debt = rnorm(5),
bonus = rnorm(5))
library(shiny)
shinyApp(
ui =
shinyUI(
fluidPage(
headerPanel("Calculating fwbs"),
sidebarPanel(
sliderInput("Income", "Please Select Income: ", min=0, max=5000,
value=2500, step=100),
sliderInput("Debt", "Please Select Debt: ", min = 0, max=2500,
value=1250, step = 100),
sliderInput("Bonus", "Have you received any bonus: ", min=0, max= 1000,
value=500, step =100),
actionButton(inputId = "btn_add_to_data",
label = "Add To Data")
),
mainPanel(
textOutput("fwbi"),
tableOutput("data")
)
)
),
server =
shinyServer(function(input, output, session){
# Store the original data at start up.
Data <- reactiveValues(
Source = Dframe
)
# Every time you click "Add Data", it will add the user-input to Data$Source
observeEvent(
input$btn_add_to_data,
{
new_row <- data.frame(income = input$Income,
debt = input$Debt,
bonus = input$Bonus)
Data$Source <- rbind(Data$Source,
new_row)
}
)
output$fwbi <- renderText({
income2<- input$Income
debt2<- input$Debt
bonus2<- input$Bonus
paste("Your fwbi is: ",
scale(Data$Source$income) +
scale(Data$Source$debt) +
scale(Data$Source$bonus))
})
output$data <- renderTable({
Data$Source
})
})
)
If you want to limit the user to only adding one row, you can use an eventReactive
Dframe <- data.frame(income = rnorm(5),
debt = rnorm(5),
bonus = rnorm(5))
library(shiny)
shinyApp(
ui =
shinyUI(
fluidPage(
headerPanel("Calculating fwbs"),
sidebarPanel(
sliderInput("Income", "Please Select Income: ", min=0, max=5000,
value=2500, step=100),
sliderInput("Debt", "Please Select Debt: ", min = 0, max=2500,
value=1250, step = 100),
sliderInput("Bonus", "Have you received any bonus: ", min=0, max= 1000,
value=500, step =100),
actionButton(inputId = "btn_add_to_data",
label = "Add To Data")
),
mainPanel(
textOutput("fwbi"),
tableOutput("data")
)
)
),
server =
shinyServer(function(input, output, session){
NewData <- eventReactive(
input$btn_add_to_data,
{
new_row <- data.frame(income = input$Income,
debt = input$Debt,
bonus = input$Bonus)
rbind(Dframe,
new_row)
}
)
output$fwbi <- renderText({
income2<- input$Income
debt2<- input$Debt
bonus2<- input$Bonus
paste("Your fwbi is: ",
scale(NewData()$income) +
scale(NewData()$debt) +
scale(NewData()$bonus))
})
output$data <- renderTable({
NewData()
})
})
)

We can change the codes to
library(shiny)
library(DT
-create a function
fscale <- function(data = NULL) {
ui <- fluidPage(
headerPanel(title = "Calculating fwbs"),
sidebarPanel(
sliderInput("Income", "Please Select Income: ", min=0, max=5000,
value=2500, step=100),
sliderInput("Debt", "Please Select Debt: ", min = 0, max=2500,
value=1250, step = 100),
sliderInput("Bonus", "Have you received any bonus: ", min=0, max= 1000,
value=500, step =100),
numericInput("n", "Number of rows to scale:", 10, min = 1, max = 100)
),
mainPanel(
textOutput("fwbi"),
dataTableOutput("data"))
)
server <- function(input, output, session){
dat_scale <- reactive({
n1 <- seq_len(input$n)
data[["Income"]][n1] <- (data$Income[n1] - input$Income)/data$Income[n1]
data[["Debt"]][n1] <- (data$Debt[n1] - input$Debt)/data$Debt[n1]
data[["Bonus"]][n1] <- (data$Bonus[n1] - input$Bonus)/data$Bonus[n1]
data
})
output$data <- renderDataTable({
dat_scale()
})
output$fwbi <- renderText({
income2<- input$Income
debt2<- input$Debt
bonus2<- input$Bonus
paste("Your fwbi is: ", income2 + debt2 + bonus2)
})
}
shinyApp(ui= ui, server = server)
}
-run the function
fscale(df1)
-output
data
set.seed(24)
df1 <- data.frame(Income = sample(0:5000, 25, replace = TRUE),
Debt = sample(0:2500, 25, replace = TRUE),
Bonus = sample(0:1000, 25, replace = TRUE))

Related

how can I get more than one plot from several selected items in a checkbox?

Good morning,
in my dashboard I inserted a checkbox to select one or more output to display. In the ui I entered the checkbox and in the server all the conditions (if ... else if ...). When I launch the app it only shows me a plot, even when I select more than one choice in the checkbox. In addition it gives me this error in console:
"Warning in if (input$checkGroup == 1) { :the condition has length > 1 and only the first element will be used"
I suppose it's telling me that I can't handle more than one choice, how do I view all the plots I choose?
ui <- fluidPage(titlePanel("IULM Dashboard"), sidebarLayout(sidebarPanel(
selectInput("selection", "Choose a Dataset:",
choices = datasets),
("Barplot","Network",'Wordcloud', "LDA-Latent topic"),
#selected = "Barplot", inline = TRUE),
checkboxGroupInput("checkGroup", label = ("Checkbox group"),
choices = list("Barplot" = 1, "Network" = 2), selected = 1, inline = TRUE),
actionButton("update", "Change"))
, mainPanel(
uiOutput("plot")))
server <- function(input, output){
datasetInput <- reactive({
input$update
isolate({
withProgress({
setProgress(message = "Processing corpus...")
getTermMatrix(input$selection)
})
})
})
output$plot <- renderUI({
if(input$checkGroup== 1 ){
output$barplot <- renderPlot({
v=datasetInput()
dtm1 = removeSparseTerms(v, 0.992)
freq <- colSums(as.matrix(dtm1))
wf = data.frame(term = names(freq), occurrences = freq)
wf <- wf[order(wf$occurrences, decreasing = TRUE),]
wf2 = subset(wf[1:input$maxB,])
ggplot(wf2, aes(term, occurrences)) +
geom_bar(stat="identity", fill="darkred", colour="black", width=0.5)+
theme(axis.text.x=element_text(angle=45, hjust=1))+
ggtitle("Word barplot")})
plotOutput(outputId = "barplot", width = 600, height = 400)
}
else if(input$checkGroup== 2 ){
output$network <- renderPlot({
v=datasetInput()
dtm1 = removeSparseTerms(v, 0.992)
rowTotals <- apply(dtm1 , 1, sum)
dtm2 <- dtm1[rowTotals> 0, ]
wdtm <- weightTf(dtm2)
dtm1 <- removeSparseTerms(wdtm, 0.96)
dfm <- as.dfm(dtm1)
textplot_network(dfm, min_freq = 0.5, omit_isolated = TRUE,
edge_color = "#1F78B4", edge_alpha = 0.5, edge_size = 2,
vertex_color = "#4D4D4D", vertex_size = 2,
vertex_labelsize = 5, offset = NULL)})
plotOutput(outputId = "network", width = 600, height = 600)}
})
}
shinyApp(ui = ui, server = server)
You can try
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
checkboxGroupInput("variable", "Variables to show:",
c("Cylinders" = "cyl",
"Transmission" = "am",
"Gears" = "gear"))
),
mainPanel(
uiOutput("plots")
)))
server <- function(input, output) {
output$plots <- renderUI({
req(input$variable)
output = tagList()
if(any(input$variable %in% "cyl")){
tmp <- mtcars$cyl
output[[1]] <- renderPlot({plot(mtcars$mpg, tmp)})
}
if(any(input$variable %in% "am")){
tmp <- mtcars$am
output[[2]] <- renderPlot({boxplot(mtcars$mpg, tmp)})
}
output
})
}
shinyApp(ui = ui, server = server)

Shiny: How to print in log the name of updated object?

I try to print in log an input which has been updated by a user in an app. Something very close can be done with observeEvent.
observeEvent(c(input$integer, input$decimal, input$range), {
flog.info(glue::glue('The user updated a value!'))
})
But I want to see in log the name of updated object without its containing values. How is it possible to do?
if (interactive()) {
library(shiny)
library(futile.logger)
library(glue)
ui <- fluidPage(
titlePanel("Sliders"),
sidebarLayout(
sidebarPanel(
sliderInput("integer", "Integer:",
min = 0, max = 1000,
value = 500),
sliderInput("decimal", "Decimal:",
min = 0, max = 1,
value = 0.5, step = 0.1),
sliderInput("range", "Range:",
min = 1, max = 1000,
value = c(200,500))
),
mainPanel(
tableOutput("values")
)
)
)
# Define server logic for slider examples ----
server <- function(input, output) {
observeEvent(c(input$integer, input$decimal, input$range), {
flog.info(glue::glue('The user updated a value!'))
})
# Reactive expression to create data frame of all input values ----
sliderValues <- reactive({
data.frame(
Name = c("Integer",
"Decimal",
"Range"),
Value = as.character(c(input$integer,
input$decimal,
paste(input$range, collapse = " "))),
stringsAsFactors = FALSE)
})
# Show the values in an HTML table ----
output$values <- renderTable({
sliderValues()
})
}
# Create Shiny app ----
shinyApp(ui, server)
}
A solution with the help of the shiny:inputchanged event:
library(shiny)
js <- "
$(document).on('shiny:inputchanged', function(e) {
if(e.name != 'updated' && e.name != '.clientdata_output_values_hidden'){
Shiny.setInputValue('updated', e.name, {priority: 'event'});
}
});"
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
titlePanel("Sliders"),
sidebarLayout(
sidebarPanel(
sliderInput("integer", "Integer:",
min = 0, max = 1000, value = 500),
sliderInput("decimal", "Decimal:",
min = 0, max = 1, value = 0.5, step = 0.1),
sliderInput("range", "Range:",
min = 1, max = 1000, value = c(200,500))
),
mainPanel(
tableOutput("values")
)
)
)
server <- function(input, output) {
observeEvent(input$updated, {
# do something with the name of the updated input,
# e.g flog.info(glue::glue(input$updated))
print(input$updated)
})
sliderValues <- reactive({
data.frame(
Name = c("Integer",
"Decimal",
"Range"),
Value = as.character(c(input$integer,
input$decimal,
paste(input$range, collapse = " "))),
stringsAsFactors = FALSE)
})
output$values <- renderTable({
sliderValues()
})
}
shinyApp(ui, server)

Object not found if created from isolate() function in Shiny

I am working on a Shiny application in which there are two slider inputs. These inputted values subset a data frame differently, and the subset of that data frame is then plotted into a scatterplot.
I am trying to prevent the scatterplot from being replotted unless the user clicks a "Go!" button. To try to achieve this, I am using the isolate() function on the slider input values, so that the data frame and plot are only updated when the "Go!" button is changed.
This seems to be working okay, but I am also trying to allow the user to use the selection tool in Plotly and see the data frame rows that correspond to that selection. However, when I attempt to do so, I receive an error ("Error: object 'datInput' not found"). This line is commented in the example below:
library(shiny)
library(plotly)
ui <- shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
sliderInput("val1", "Value 1:", min = 0, max = 1, value=0.5, step=0.1),
sliderInput("val2", "Value 2:", min = 0, max = 1, value=0.5, step=0.1),
actionButton("goButton", "Go!")
),
mainPanel(
plotlyOutput("plot1"),
verbatimTextOutput("click")
)
))
server <- shinyServer(function(input, output) {
set.seed(1)
dat <- data.frame(Case = paste0("case",1:15), val1=runif(15,0,1), val2=runif(15,0,1))
dat$Case <- as.character(dat$Case)
xMax = max(dat$val1)
xMin = min(dat$val1)
yMax = max(dat$val2)
yMin = min(dat$val2)
maxTemp = max(abs(xMax), abs(xMin))
observeEvent(input$goButton,
output$plot1 <- renderPlotly({
# Use isolate() to avoid dependency on input$val1 and input$val2
datInput <- isolate(subset(dat, val1 > input$val1 & val2 > input$val2))
p <- qplot(datInput$val1, datInput$val2) +xlim(0, ceiling(maxTemp)) +ylim(0,1)
ggplotly(p)
})
)
d <- reactive(event_data("plotly_selected"))
output$click <- renderPrint({
if (is.null(d())){
"Click on a state to view event data"
}
else{
#str(d()$pointNumber) #Seems to be working
datInput[d()$pointNumber,] #Error: object 'datInput' not found
}
})
})
shinyApp(ui, server)
Any ideas for a workaround for this issue would be appreciated!
EDIT:
Here is the solution as per #mlegge. I simply added the output after the user selects certain points:
library(shiny)
library(plotly)
ui <- shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
sliderInput("val1", "Value 1:", min = 0, max = 1, value=0.5, step=0.1),
sliderInput("val2", "Value 2:", min = 0, max = 1, value=0.5, step=0.1),
actionButton("goButton", "Go!")
),
mainPanel(
plotlyOutput("plot1"),
verbatimTextOutput("click")
)
))
set.seed(1)
dat <- data.frame(Case = paste0("case",1:15), val1=runif(15,0,1), val2=runif(15,0,1))
dat$Case <- as.character(dat$Case)
xMax = max(dat$val1)
xMin = min(dat$val1)
yMax = max(dat$val2)
yMin = min(dat$val2)
maxTemp = max(abs(xMax), abs(xMin))
server <- shinyServer(function(input, output) {
# datInput only validated once the go button is clicked
datInput <- eventReactive(input$goButton, {
subset(dat, val1 > input$val1 & val2 > input$val2)
})
output$plot1 <- renderPlotly({
# will wait to render until datInput is validated
plot_dat <- datInput()
p <- qplot(plot_dat$val1, plot_dat$val2) + xlim(0, ceiling(maxTemp)) +ylim(0,1)
ggplotly(p)
})
d <- reactive(event_data("plotly_selected"))
output$click <- renderPrint({
if (is.null(d())){
"Click on a state to view event data"
}
else{
#str(d()$pointNumber)
datInput()[d()$pointNumber+1,] #Working now
}
})
})
shinyApp(ui, server)
You are not using isolate properly, a better solution is an eventReactive:
library(shiny)
library(plotly)
ui <- shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
sliderInput("val1", "Value 1:", min = 0, max = 1, value=0.5, step=0.1),
sliderInput("val2", "Value 2:", min = 0, max = 1, value=0.5, step=0.1),
actionButton("goButton", "Go!")
),
mainPanel(
plotlyOutput("plot1")
)
))
set.seed(1)
dat <- data.frame(Case = paste0("case",1:15), val1=runif(15,0,1), val2=runif(15,0,1))
dat$Case <- as.character(dat$Case)
xMax = max(dat$val1)
xMin = min(dat$val1)
yMax = max(dat$val2)
yMin = min(dat$val2)
maxTemp = max(abs(xMax), abs(xMin))
server <- shinyServer(function(input, output) {
# datInput only validated once the go button is clicked
datInput <- eventReactive(input$goButton, {
subset(dat, val1 > input$val1 & val2 > input$val2)
})
output$plot1 <- renderPlotly({
# will wait to render until datInput is validated
plot_dat <- datInput()
p <- qplot(plot_dat$val1, plot_dat$val2) + xlim(0, ceiling(maxTemp)) +ylim(0,1)
ggplotly(p)
})
})
shinyApp(ui, server)
You'll notice that your data generation has been moved outside the server, this is because it only needs to be run once.
You also should never wrap an output object in an observer, instead control the input data with reactives.

Table output of values Shiny

I am trying to generate a table/list in Shiny of the values sampled from a probability distribution ( a list of the sampled values in a table format). I'm new to coding so this is like a foreign language to me. There is probably a lot of errors in the code although I can get it to run just not show the table.
library(shiny)
ui <- fluidPage(
sidebarPanel(
selectInput("dis","Please Select Probability Distribution Type:",
choices = c("Normal")),
sliderInput("sampleSize","Please Select Sample Size:",
min = 0,max = 5000,value = 1000,step = 100),
sliderInput("bins","Please Select Number of Bins:",
min = 1,max = 50,value = 10),
numericInput("sampleMean","Please Enter Sample Mean:",
min = 0,max = 5000,value = 2500,step = 10),
numericInput("sampleSd","Please Enter Standard Deviation:",
min = 0,max = 5000,value = 2,step = 10)
),
fluidRow(
column(12,
dataTableOutput("table"))
),
mainPanel(
plotOutput("histogram")
)
)
server <- function(input, output){
output$histogram <- renderPlot({
distType <- input$dis
n <- input$sampleSize
bins <- seq(min(input$bins), max(input$bins), length.out = input$bins + 1)
if(distType=="Normal"){
randomVec <- rnorm(n,mean = as.numeric(input$sampleMean),sd=as.numeric(input$sampleSd))
}
hist(randomVec,breaks=input$bins,col="red")
})
output$table <- renderDataTable({
distType <- input$dis
n <- input$sampleSize
if(distType=="Normal"){
randomVec <- rnorm(n,mean = as.numeric(input$sampleMean),sd= as.numeric(input$sampleSd))
}
sample(randomVec,100,replace = TRUE)
})
}
shinyApp(ui = ui, server = server)
From ?renderDataTable :
Arguments
expr An expression that returns a data frame or a matrix.
So you can do this:
output$table <- renderDataTable({
distType <- input$dis
n <- input$sampleSize
if(distType=="Normal"){
randomVec <- rnorm(n,mean = as.numeric(input$sampleMean),sd= as.numeric(input$sampleSd))
}
data.frame(sample(randomVec,100,replace = TRUE))
})

Update of the variable by constant in shiny

The community helped me in developing this code
library(shiny)
server <- shinyServer(function(input, output, session) {
values <- reactiveValues()
values$df <- data.frame(N = numeric(0), A = numeric(0), C = numeric(0))
newEntry <- observeEvent(input$update,{
gr <- 10 + input$n
newLine <- isolate(c(input$n, input$nr1, gr))
values$df[nrow(values$df) + 1,] <- c(input$n, input$nr1, gr)
})
output$table1 <- renderTable({values$df})
})
ui <- shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
sliderInput("nr1", "Give a number: ", min = 0, max = 100, value = 0, step = 2),
sliderInput("n", "N:", min = 10, max = 1000, value = 200, step = 10),
actionButton("update", "Update Table"))),
column(6, tableOutput("table1"))
)
))
shinyApp(ui, server)
And I come to a new problem with that.
Now, I'd like that the app do like this: on click on the update, the variable A should always add a 5 i.e. if I have starting value of 5 than on the next click it should be 10 than 15, 20 etc?
Now when I click update the same number appears continously
Is this what you want? Also you dont need the isolate in there.
rm(list = ls())
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("submitButton example"),
fluidRow(
column(3, wellPanel(
sliderInput("nr1", "Give a number:", min = 1, max = 100, value = 1, step = 1),
sliderInput("n", "N:", min = 10, max = 1000, value = 200, step = 10),
actionButton("update", "Update Table"))),
column(6, tableOutput("table1"))
)
))
server <- shinyServer(function(input, output, session) {
values <- reactiveValues()
values$df <- data.frame(N = numeric(0), A = numeric(0), C = numeric(0))
newEntry <- observeEvent(input$update,{
if(!is.null(input$nr1) & is.null(values$A)){
values$A <- input$nr1
}
if(nrow(values$df) > 0){
values$A <- values$A + 5
}
gr <- 10 + input$n
values$df[nrow(values$df) + 1,] <- c(input$n, values$A, gr)
})
output$table1 <- renderTable({values$df})
})
shinyApp(ui, server)

Resources