I am attempting to run a regression that allows users to determine regression inputs, and then provide an output that is the regression summary. For whatever reason, the output is not coming out correct, and I have looked everyone on the internet to find a solution. I am hoping somebody can help.
For clarification, this is in shiny.
Here is my server code:
shinyServer(
function(input,output,session) {
mod <- eventReactive(input$analysis,{
response <- data[,2]
explan1 <- data[,input$Explan1]
explan2 <- data[,input$Explan2]
explan3 <- data[,input$Explan3]
mod1 <- lm(response~explan1+explan2+explan3)
} )
output$modelSummary <- renderPrint({
(summary(mod()$mod1))
})
output$ColumnNames <- renderPrint({
as.data.frame(colnames(data))
})
}
)
summary(model)
And my ui code
shinyUI(
fluidPage(
titlePanel("What does it take for a Hockey Team to Win?"),
titlePanel("Please select the column numbers for three variables to regress on"),
sidebarLayout(
sidebarPanel(
verbatimTextOutput("ColumnNames"),
numericInput("Explan1","Explanatory Variable 1",3,min = 3, max = 13),
numericInput("Explan2","Explanatory Variable 2",4,min = 3,max = 13),
numericInput("Explan3","Explanatory Variable 3",5,min = 3, max = 13)
),
mainPanel(
actionButton("analysis","Analyze!"),
verbatimTextOutput("modelSummary")
)
)
)
)
When I run the app, select the input columns (which are by number rather than name. I hope to fix this later) and click analyze, I get the following output:
Length Class Mode
0 NULL NULL
I haven't been able to find much relevant information on this output. I hope you all can help.
Thank you in advance.
You're just calling the reactive incorrectly, it should be: summary(mod()) instead of summary(mod()$mod1). Reactives behave very much like functions the way that they return objects.
Here is a fully reproducible example, with an example on how to use a formula instead of individually selecting the columns:
col_names <- names(mtcars)
ui <- fluidPage(
sidebarPanel(
verbatimTextOutput("ColumnNames"),
selectInput("Response", "Response Variable", choices = col_names, selected = "mpg"),
selectInput("Explan1","Explanatory Variable 1", choices = col_names, selected = "cyl"),
selectInput("Explan2","Explanatory Variable 2", choices = col_names, selected = "disp"),
selectInput("Explan3","Explanatory Variable 3", choices = col_names, selected = "wt")
),
mainPanel(
actionButton("analysis","Analyze!"),
verbatimTextOutput("modelFormula"),
verbatimTextOutput("modelSummary")
)
)
server <- function(input, output, session) {
myformula <- reactive({
expln <- paste(c(input$Explan1, input$Explan2, input$Explan3), collapse = "+")
as.formula(paste(input$Response, " ~ ", expln))
})
mod <- eventReactive(input$analysis, {
lm(myformula(), data = mtcars)
})
output$modelFormula <- renderPrint({
myformula()
})
output$modelSummary <- renderPrint({
summary(mod())
})
}
shinyApp(ui, server)
Screenshot:
Related
I am quite new to R shiny and I am trying to build a small shiny app but I don't know where I went wrong.
I am trying to get multiple user input via text area to filter my table output. Moreover, i want to control the columns to show in the table as well. Code is running fine for showing the columns but it is working only with one input value in the text area, it is not working with multiple user inputs.
I want to filter the table output with multiple user inputs as well.
For example for this code snippet it should return table when I write "honda,audi,bmw" in the text area input.
library(shiny)
library(shinyWidgets)
library(DT)
df <-mtcars
#ui
shinyApp(
ui = fluidPage(
titlePanel("Trial 1"),
sidebarLayout(
sidebarPanel(
#to take multiple user input
textAreaInput(
"text_input",
label = "Write multiple input separated by comma"
),
#to slect the columns to be added
pickerInput(
inputId = "somevalue",
label = "Columns to add",
choices = colnames(df),
options = list(`actions-box` = TRUE),
multiple = TRUE
),
#action button tot show the table
actionBttn(
"show_table",
label = "Show",
size = "sm",
color = "default",
block = TRUE
),
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("Table", DT::dataTableOutput("table")),
tabPanel("Summary", verbatimTextOutput("summary"))
)
)
)
),
server = function(input, output,session) {
data <- observeEvent(input$show_table,{
text_input <- trimws(strsplit(input$text_input, ",")[[1]])
output$summary <- renderPrint({
summary(data())
})
output$table <- DT::renderDT({
df_sub <- df[df$make %chin% input$text_input, input$somevalue]
#df_sub = df[ ,input$somevalue]
datatable(df_sub,
caption = "PLease enter the changes by double clicking the cell",
editable = 'cell')
})
})
}
)
There isn't a 'make' variable in the data. I guess you refer to the first word of the row name as the make of the car. Then the strings you entered could be matched with the make of the car.
server = function(input, output,session) {
data <- observeEvent(input$show_table,{
brand <- word(rownames(df), 1)
text_input <- strsplit(input$text_input, ",")[[1]]
df_sub <- df[brand %in% text_input, input$somevalue]
output$summary <- renderPrint({
summary(df_sub)
})
output$table <- DT::renderDT({
datatable(df_sub,
caption = "PLease enter the changes by double clicking the cell",
editable = 'cell')
})
output$test <- renderText({
text_input
})
})}
How to display the entire row of a selected value?
What we have is a drop down menu where a certain values of a defined column can be selected. If one of the values in the the drop down menu is selected the entire row where this value is located should be displayed.
In the following case the values that can be selected in a drop down menu are the letters x, y, z. e.g. If "y" is selected in the drop down menu, it should be displayed only the entire second row inlcuding the column names.
library(shiny)
Values <- data.frame(A = 1:3, B = letters[24:26], C = 11:13)
shinyApp(
ui = fluidPage(
sidebarPanel(
selectInput("Values", "Values", Values$B),
mainPanel(
tableOutput("ValuesTable")
)
)
),
server = function(input, output) {
output$ValuesTable <- renderTable({
Values
})
})
What I´ve found so far are solutions with _rows_selected. However, it doesn´t fit to my problem or I´m not able to make use of it, yet.
You can filter values in the appropriate column using dplyr::filter() with your select input "Values" in the renderTable() function.
library(shiny)
library(dplyr) # for filter() function
library(magrittr) # for pipe operator
Values <- data.frame(A = 1:3, B = letters[24:26], C = 11:13)
shinyApp(
ui = fluidPage(
sidebarPanel(
selectInput("Values", "Values", Values$B),
mainPanel(
tableOutput("ValuesTable")
)
)
),
server = function(input, output) {
output$ValuesTable <- renderTable({
Values %>%
dplyr::filter(B == input$Values)
})
})
I have been trying to merge data with another data set based on input from a drop down. I have just started learning R and have run into some problems and want to know if there is a better way of going about this.
I am getting an error that it cannot coerce class c(ReactiveExpr, reactive) to a data frame.
library(shiny)
library(plyr)
library(dplyr)
library(xlsx)
server <- function(input, output){
annotation1 <- read.xlsx("input1.xlsx", sheetIndex = 1, header = TRUE)
annotation2 <- read.xlsx("input2.xlsx", sheetIndex = 1, header = TRUE)
data_input <- eventReactive(input$userfile, {
df <- read.xlsx(input$userfile$datapath, sheetIndex = 1, header = TRUE)
})
output$data_input <- renderTable(data_input())
output$annotation <- renderTable(annotation)
data_species <- c("Set1", "Set2")
# Drop-down selection box for which data set
output$choose_species <- renderUI ({
selectInput("species", "Species", as.list(data_species))
})
output$mergeddata <- renderTable({
if(input$species == "Set1"){
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))
}
else if(input$species == "Set2"){
eventReactive("Set2",({left_join(data_input(), annotation2, by = c("Column1" = "Column1"))}))
}
})
}
ui <- fluidPage(
titlePanel(
div("Test")
),
sidebarLayout(
sidebarPanel(
fileInput("userfile", "Input File", multiple =FALSE,
buttonLabel = "Browse Files", placeholder = "Select File"),
uiOutput("choose_species"),
uiOutput("choose_annotations"),
),
mainPanel(
tableOutput("mergeddata"),
br()
),
),
)
# Run the application
shinyApp(ui = ui, server = server)
In general, you approach seems ok. The error you get is from the line
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))
An eventReactive returns an (unevaluated) reactive expression which you try to render as data.frame with renderTable. To circumvent this, you could use:
eventReactive("Set1",({left_join(data_input(), annotation1, by = c("Column1" = "Column1"))}))()
However, here you don't need eventReactive, because your reactivity comes from input$species (you want to change the table output based on this input). Therefore, you can just use:
output$mergeddata <- renderTable({
if(input$species == "Set1"){
merge_data <- annotation1
} else {
merge_data <- annotation2
}
left_join(data_input(), merge_data, by = c("Column1"))
})
I want to download the output of this App which I made but there is an error and when I open the downloaded data it is empty.I make a data set by output$other_val_show and I want to download it. Any advice?
The following code in for the UI section.
library(shiny)
library(quantreg)
library(quantregGrowth)
library(plotly)
library(rsconnect)
library(ggplot2)
library(lattice)
ui = tagList(
tags$head(tags$style(HTML("body{ background: aliceblue; }"))),
navbarPage(title="",
tabPanel("Data Import",
sidebarLayout(sidebarPanel( fileInput("file","Upload your CSV",multiple = FALSE),
tags$hr(),
h5(helpText("Select the read.table parameters below")),
checkboxInput(inputId = 'header', label = 'Header', value = FALSE),
checkboxInput(inputId = "stringAsFactors", "StringAsFactors", FALSE),
radioButtons (inputId = 'sep', label = 'Separator',
choices = c(Comma=',',Semicolon=';',Tab='\t', Space=''), selected = ',')
),
mainPanel(uiOutput("tb1"))
)),
tabPanel("Interval",
sidebarLayout(sidebarPanel(
uiOutput("model_select"),
uiOutput("var1_select"),
uiOutput("rest_var_select"),
#uiOutput("testText1"), br(),
#textInput("Smooting Parameter min value", "Smooting Parameter max value", value = "")
sliderInput("range", "Smooth Parameter range:",min = 0, max = 1000, value = c(0,100)),
downloadButton('downloadData', 'Download')
),
mainPanel(helpText("Selected variables and Fitted values"),
verbatimTextOutput("other_val_show")))),
tabPanel("Model Summary", verbatimTextOutput("summary")),
tabPanel("Scatterplot", plotOutput("scatterplot"))#, # Plot
#tabPanel("Distribution", # Plots of distributions
#fluidRow(
#column(6, plotOutput("distribution1")),
#column(6, plotOutput("distribution2")))
#)
,inverse = TRUE,position="static-top",theme ="bootstrap.css"))
The following code in for the Server section. (I want to download the output which is "gr" and I want to download it by downloadHandler function.
server<-function(input,output) {
data <- reactive({
lower <- input$range[1]
upper <- input$range[2]
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=input$sep, header = input$header, stringsAsFactors = input$stringAsFactors)
})
output$table <- renderTable({
if(is.null(data())){return ()}
data()
})
output$tb1 <- renderUI({
tableOutput("table")
})
#output$model_select<-renderUI({
#selectInput("modelselect","Select Algo",choices = c("Reference Interval"="Model"))
#})
output$var1_select<-renderUI({
selectInput("ind_var_select","Select Independent Variable", choices =as.list(names(data())),multiple = FALSE)
})
output$rest_var_select<-renderUI({
checkboxGroupInput("other_var_select","Select Dependent Variable",choices =as.list(names(data()))) #Select other Var
})
output$other_val_show<-renderPrint({
input$other_var_select
input$ind_var_select
f<-data()
lower <- input$range[1]
upper <- input$range[2]
library(caret)
library(quantregGrowth)
dep_vars <- paste0(input$ind_var_select, collapse = "+")
after_tilde <- paste0("ps(", dep_vars, ", lambda = seq(",lower,",",upper,",l=100))")
dyn_string <- paste0(input$other_var_select, " ~ ", after_tilde)
Model<-quantregGrowth::gcrq(as.formula(dyn_string),tau=c(0.025,0.975), data=f)
temp <- data.frame(Model$fitted)
gr <- cbind(f, temp)
print(gr)
})
output$downloadData <- downloadHandler(
write.csv(gr, file, row.names = FALSE)
)
}
shinyApp(ui=ui,server=server)
It's hard to fully answer this without a minimal reproducibile example, but here's what I would try:
Create gr outside of renderPrint
Use gr() in downloadHandler
Rewrite downloadHandler to include content and filename arguments
Here's a minimal example with the same logic as your app, i.e. create a reactive dataframe which is both printed (renderPrint) and downloadable (downloadHandler).
library(shiny)
ui <- navbarPage(title = "Example",
tabPanel("First",
selectInput("fruit", "Fruit", c("apple", "orange", "pear")),
h4("Output from renderPrint:"),
textOutput("other_val_show"),
h4("Download Button: "),
downloadButton("downloadData")))
server <- function(input, output) {
gr <- reactive({
data.frame(fruit = input$fruit)
})
output$other_val_show <- renderPrint({
print(gr())
})
output$downloadData <- downloadHandler(
filename = "example.csv",
content = function(file) {
write.csv(gr(), file)
})
}
shinyApp(ui, server)
You define gr inside the scope of that renderPrint function so it isn't available to downloadHandler. You should define gr as a reactive value somewhere outside that function. That way, when you assign it in the renderPrint function, it will be accessible to the entire scope of your program.
In the future, it would be helpful to provide the text of any error messages you get - they are often quite helpful to solving problems.
I'm trying to use Shiny + ShinyBS to create a collapsible panel whitch contains a bunch of column values per column.
However, I'm having trouble in applying do.call correctly (or in the sequence I want).
Source code for server.R:
require(shiny)
library(lazyeval)
library(shinyBS)
l <- lapply(mtcars, function(x) unique(x))
shinyServer(function(input, output) {
output$plot <- renderUI({
col_list <- lapply(1:length(l), function(i) {
col <- l[[i]]
a <- lapply(1:min(length(col), 10), function(j) {
interp(quote(bsToggleButton(nm,lb)),
.values=list(nm = paste0(names(l)[i],
'_val_',
j),
lb = col[j]))
})
pars <- list(inputId = paste0('btng_',
names(l)[i]),
label = '', value = '', a)
interp(quote(bsCollapsePanel(names(l)[i],
fluidRow(
column(4,
do.call(bsButtonGroup,
unlist(pars))
)
),
id = nm, value = val)),
.values = list(i = i,
nm = paste0('test_',i),
val = '')
)
})
pars2 <- list(multiple = TRUE,
open = "test_1",
id = "collapse1",
col_list)
do.call(bsCollapse, unlist(pars2))
})
})
Source code for ui.R:
require(shiny)
shinyUI(
fluidPage(
uiOutput('plot')
)
)
The code can NOT run! The problem is pars seems to be static, it only contains the value of the first iteration.
Firstly, the code was still not reproducible as is. I suspect you had run parts of the provided code within your environment (e.g. the 'pars' object was not found with your provided code on my machine).
Second, I think you have just made your apply statements too complex. The idea of apply statements is to improve readability of your code as opposed to for loops. Here you have crammed so much in to the lapply statements that it is difficult to parse out anything.
To address this, I broke the components apart into their own lapply statements (which is far more approachable now). What was happening with your previous code is that your pars object was taking all the variables from the a object. Once these components were separated, I could easily just alter the pars statement to iterate through each a element. This provides the different values for each iteration (i.e. variable). I have only included the server.R as there is not changes to your ui.R
As a followup to your comments below, you are correct that the interp and quote arguments are unnecessary (I generally avoid them again for clarity, my personal preference). As for best practices, I sum it up in one concept 'clarity then performance'. If you are unsure about your objects then LOOK AT THEM! Below you will find an updated server.R file. I have also minimally commented it. You will also find an example of accessing the bsGroupButton values. You can see it is the group id that you must reference. This should get you started (be sure to add tableOutput('result') to your ui.R. I highly recommend you look into the documentation of ShinyBS or at least the demo page.
Concise and annotated server.R
require(shiny)
library(shinyBS)
l <- lapply(mtcars,function(x)unique(x))
shinyServer(function(input, output) {
output$plot <- renderUI({
# Create your buttons
a <- lapply(1:length(l), function(i){
col <- l[[i]]
lapply(1:min(length(col),10), function(j){
bsButton(paste0(names(l)[i], '_val_', j), label=col[j], value=col[j])
})
})
# add the additional arguments for your future bsButtonGroup call
pars <- lapply(1:length(l), function(i) {
list(inputId =paste0('btng_',names(l)[i]), label = '', value = '',a[[i]])
})
col_list<-lapply(1:length(l), function(i) {
# separate the components for clarity
rawButtons <- unlist(pars[i], recursive=F)
buttons <- do.call(bsButtonGroup, c(rawButtons[[4]], inputId=rawButtons$inputId))
# collapse the groups into panels
bsCollapsePanel(title=names(l)[i],
buttons, id=paste0('test_',i), value='')
})
# Collapse everything, no need for pars2, just add elements in a vector
do.call(bsCollapse, c(col_list, multiple=TRUE, open="test_1", id="collapse1"))
})
output$result<- renderTable({
df <- cbind(c("mpg toggle button", c(deparse(input$btng_mpg))))
return(df)
})
})
original answer for server.R
require(shiny)
library(shinyBS)
require(lazyeval)
l <- lapply(mtcars,function(x)unique(x))
shinyServer(function(input, output) {
output$plot <- renderUI({
a <- lapply(1:length(l), function(i) {
col <- l[[i]]
lapply(1:min(length(col),10), function(j) {
interp(
quote(bsToggleButton(nm,lb))
,.values=list(nm=paste0(names(l)[i],'_val_', j),lb=col[j]))
})
})
pars <- lapply(1:length(l), function(i) {
list(inputId =paste0('btng_',names(l)[i]), label = '', value = '',a[[i]])
})
col_list<-lapply(1:length(l), function(i) {
interp(
quote(
bsCollapsePanel(names(l)[i],
fluidRow(
column(4,
do.call(bsButtonGroup,unlist(pars[i]))
)
),
id=nm,value=val))
,.values=list(i=i,nm=paste0('test_',i),val='')
)
})
pars2 <- list(multiple = TRUE, open = "test_1", id = "collapse1",col_list)
do.call(bsCollapse,unlist(pars2))
})
})