non-numeric argument to binary operator in shiny app - r

This is my code below, I think it may just be a silly mistake but I have spent the last 5 days trying to find where I went wrong in my app:-
ui <- fluidPage(h1("Left Ventricular Hypertrophy"),
titlePanel("Regression Model"),
sidebarLayout(
sidebarPanel(
h3("Marginal Histogram"),
selectInput("marhis1", "X:", choices = unique(colnames(lvh))),
selectInput("marhis2", "Y:", choices = unique(colnames(lvh)), selected = "sbp"),
sliderInput("bin", "Bin Width:", min = 1, max = 100, value = 10),
h3("Box Plot"),
selectInput("Variable4", "llvmi or sbp:", choices = c("llvmi", "sbp")),
selectInput("Variable5", "Grouped by:", choices = c("sex", "card", "dgp", "surv")),
mainPanel(
h3("Marginal Histogram"),
plotOutput("hist"),
br(),
h3("Boxplot"),
plotOutput("Box")
)
)
)
server <- function(input, output) {
lvh <- read.table('lvh.dat.txt', header = T)
output$hist <- renderPlot({
marg <- ggplot(lvh, aes(input$marhis1, input$marhis2) + geom_point() + theme_light() +
xlab(input$marhis1) + ylab(input$marhis2))
ggMarginal(marg, input$marhis1, input$marhis2, type = "histogram", binwidth = input$bin)
})
output$Box <- renderPlot({
choice2 <- data.frame(x=lvh[input$Variable4], y=lvh[input$Variable5])
ggplot(choice2, aes(lvh[input$Variable4], lvh[input$Variable5]) + geom_boxplot() + theme_light() +
xlab(input$Variable4) + ylab(input$Variable5))
})
}
shinyApp(ui = ui, server = server)
I keep getting an error of non-numeric argument to binary operator in both of the plots when I run app, could anyone help

First, let me encourage you to always provide code samples that are easy to inspect. Since, from your comment conversation in the original post, one can see that you did not quite get what that means: Make the code snippet so that simple copy + paste will be enough to run into the errors you are facing.
At least four people looked at your code and everyone was immediately discouraged to invest some patience into it.
Otherwise it would have been easy to detect, that you are just missing a parenthesis in the part
ggplot(lvh, aes(input$marhis1, input$marhis2) + geom_point()
where it must be
ggplot(lvh, aes(input$marhis1, input$marhis2)) + geom_point()
(of course eliminating the also misplaced original closing bracket).
Edit: Same goes for the second call to ggplot. More on that: ggplot works by adding layers to the plot. That is why you have to add (+) the ggplot(...) generated elements. Not adding options inside the call to ggplot.

Related

ggplot not working properly inside eventReactive() in shiny

I wasted hours to find out why my plot is automatically updating itself when I change inputs while it was supposed to wait for the Run button but it simply ignored that step and I ended up finally finding ggplot as the trouble maker!!! This is my minimal code:
library(ggplot2)
library(tidyverse)
varnames <- names(cars)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
column(
width = 12,
# Variables Inputs:
varSelectInput("variables", "Select Input Variables", cars, multiple = TRUE),
selectizeInput("outvar", "Select Output Variable", choices = varnames, "speed", multiple = F),
# Run Button
actionButton(inputId = "run", label = "Run")
)
)
),
# Main panel for displaying outputs ----
mainPanel(
plotOutput("plot")
)
)
)
server <- function(input, output, session) {
df <- reactive({
cars %>% dplyr::select(!!!input$variables, input$outvar)
})
plt <- eventReactive(input$run, {
#Just creating lm formula
current_formula <- paste0(input$outvar, " ~ ", paste0(input$variables, collapse = " + "))
current_formula <- as.formula(current_formula)
#Fitting lm
fit <- lm(current_formula, data = df())
pred <- predict(fit, newdata = df())
#Plotting
ggplot(df(), aes(df()[, input$outvar], pred)) +
labs(x = "Observed", y = "Predicted") +
geom_point() +
theme_bw()
#plot(df()[, input$outvar], pred) #This one works fine!!!!
})
output$plot <- renderPlot({
plt()
})
}
# Run the application
shinyApp(ui = ui, server = server)
If you run this, you'll notice that ggplot doesn't care anymore about the Run button after the 1st run and it keeps updating as you change the inputs!! However, if you use the simple base plot function (which I put in a comment in the code) there wouldn't be any problems and that works just fine! Sadly I need ggplot in my app because base plot is ugly. I am seeing suggestion for using isolate() to solve this issue but I have no clue where isolate() should be put to fix my problem also it doesn't make sense to use isolate() when base plot function works fine without it and it's the ggplot that makes the problem. Any explanation would be appreciated.
The issue is that ggplot aesthetics are lazy evaluated. You really want to put symbols into the aes() rather that reactive data values. Change your plotting code to
ggplot(df(), aes(.data[[input$outvar]], pred)) +
labs(x = "Observed", y = "Predicted") +
geom_point() +
theme_bw()
With ggplot you use the .data pronoun to access the current data source rather than trigger the reactive df() object again.

R Shiny reactivity error, how can I fix it?

i have the following shiny application:
Dataset:(https://www.kaggle.com/rush4ratio/video-game-sales-with-ratings)
library(shinythemes)
library(shiny)
library(ggplot2)
ui = navbarPage(theme = shinytheme("united"),"Video Games Dashboard",
tabPanel("Dashboard",
sidebarLayout(
sidebarPanel(
selectInput(inputId = "dataset",
label = "Choose a dataset:",
choices = colnames(data)),
),
mainPanel(
plotOutput(outputId = "ggPlot"),
plotOutput(outputId = "ggPlot2"),
)
)
),
tabPanel("Summary",
)
)
server <- function(input, output) {
output$ggPlot <- renderPlot({
ggplot ( data=data,aes(x=Global_Sales, y=input$dataset)) +
geom_bar(stat="identity" ,fill="steelblue") +
coord_flip() +
theme_minimal()
})
output$ggPlot2 <- renderPlot({
ggplot ( data=data,aes(x=Global_Sales, y=Platform)) +
geom_bar(stat="identity" ,fill="steelblue") +
theme_minimal()
})
}
shinyApp(ui = ui, server = server)
Which looks like this:
As you can see I want to do the same in the first plot("ggPlot") like in the second plot("ggPlot2") just that the first plot is reactive and you can select every column of the datatable to display it in the plot.
However, I get this message all the time:
Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
Does anybody know how to fix this? Is this approach even possible?
Thanks!
This warning appears when there's a single item on one of the two axes - see this shiny issue.
But your code does not produce the plot you expect: input$dataset is the name of a column of the data, hence it is a string, and then when you do aes(x = Global_Sales, y = input$dataset), the y argument of aes is not set to a variable of the data, it is set to a string. So you have a single item on the y-axis, hence the warning.
To set the arguments of aes to some variables of the data when you have the names of these variables, you can use aes_string:
aes_string(x = "Global_Sales", y = input$dataset)

Cross tab to complement stacked bar plot in Shiny app

I am having trouble creating a shiny app that creates a dynamic cross tab where one of the variables can be changed.
That is, I would like to create an app that creates a cross tab that shows the percentage of students that passed against each characteristic, as well as displaying this in a bar plot.
The bar plot is no problem. I cannot figure out how to vary the input into the cross tab.
The output$my_table section in the server object is where the problem is.
Any assistance would be greatly appreciated
library(shiny)
library(ggplot2)
students <- data.frame(Passed = c("Y","Y","Y","Y","Y","Y","N","N"), Gender = rep(c("Male","Female"), each = 4),
Subject = rep(c("Maths","Science"), times = 4),Campus =c(rep(c("Victoria"), times = 7), "NSW"))
ui <- fluidPage(
titlePanel("Percentage Passed by Characteristic"),
sidebarLayout(sidebarPanel(
selectInput(
"Characteristic",
"Student characteristic",
choices = colnames(students)[!colnames(students) %in% c("Passed")],
selected = colnames(students)[2]
)
),
mainPanel(
tabPanel("Plot",
fluidRow(
plotOutput("barplot"),
verbatimTextOutput("summary"))
),
tabPanel("Summary",
tableOutput("my_table"))
)
))
server <- function(input, output) {
output$barplot <- renderPlot({
var <- input$Characteristic
gg <-
ggplot(students, aes_string(x = var, fill= "Passed"))
gg <- gg + geom_bar(position = "Stack")
gg
})
output$my_table <- renderTable({
var <- input$Characteristic
prop.table(table(students$Passed, students$var),1)
})
}
# Create Shiny object
shinyApp(ui = ui, server = server)
The problem is that students$var refers to a column literally named "var", whereas you want the column named by the value of var: students[[var]].
This is addressed the question "access data frame column using variable", and answered in the last sentence of the winning answer. access data frame column using variable
I diagnosed the problem by running your code in an interactive R session, setting var to Gender, then running the prop.table(... line, which gives the error:
Error in table(students$Passed, students$var) :
all arguments must have the same length
The next problem you'll face is formatting the resulting prop.table, but that deserves another question.

R: Referring to a variable name with special characters

For a Shiny program I'm writing, I have input variables that contain a dash, commas and brackets. Spaces I can substitute out but the rest are needed since they are refering to chemical compounds and don't make sense without them. As expected, these characters make the Shiny app unable to find the desired variable; whilst variables with none of these characters work fine.
EDITED: The code below is a test Shiny app. With Chemical-X(a,b) the app returns "could not find function X". With Chemical.B the app returns "object Chemical.B not found" which is the desired result since the app sees the chemical as an object and not some function that doesn't exist.
library (shiny)
library (ggplot2)
dat <- as.data.frame(c("Chemical-X(a,b)", "Chemical.B"))
dat[,2] <- (c(6,3))
colnames(dat) <- c("Chemical", "Count")
ui <- fluidPage(
titlePanel("SE Test"),
sidebarLayout(
sidebarPanel(
selectInput(inputId = "varX",
label = "Chemical",
choices = dat[,1],
width = "200px"),
selectInput(inputId = "varY1",
label = "Count",
choices = dat[,2],
width = "200px")
),
mainPanel(
plotOutput("chemPlot")
)
)
)
server <- function(input, output){
output$chemPlot <- renderPlot({
plot.data <- ggplot(data = dat)
point <- plot.data + geom_point(
aes_string(x = input$varX, y = input$varY1))
plot(point)
})
}
shinyApp(ui = ui, server = server)
Is there a known way of doing this or will I need to come up with some viable work around? I have tried using backticks as suggested here but this hasn't worked.
Thanks, Matt
I have found that backticks and aes_string usually works for me.
library("ggplot2")
my_dodgy_var <- "name with~special character"
mtcars[[my_dodgy_var]] <- mtcars$cyl
ggplot(mtcars, aes_string(x=paste0("`", my_dodgy_var, "`"), y="mpg")) +
geom_point()
I often use a helper function paste_aes to do this, eg:
paste_aes <- function(x) paste0("`", x, "`")
I've fixed it now by calling as.name the Shiny input$ variable. For the example above it would look like this.
server <- function(input, output){
output$chemPlot <- renderPlot({
plot.data <- ggplot(data = dat)
point <- plot.data + geom_point(
aes_string(x = as.name(input$varX), y = as.name(input$varY1)))
plot(point)
This appears to work now as intended. Thank you aocall for your efforts.

How can I display time series graph with its forecasting line?

The object is gettig parameters from users to make them understand the forecasting techniques. Therefore, i would like to begin with moving average. Eventhough the work is quite simple, i couldnt manage and i have some issues.
One error occurs: ERROR: missing value where TRUE/FALSE needed.
I do not understand why do I get this?
I want to show forecasted values for next period. But with this ready formula does not provide that?
`
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Forecasting Methods"),
sidebarPanel(
h3(strong("Moving Average",style = "color:black")),
br(),
sliderInput("ord","Order Size:",min = 1, max = 100, step= 1, value = 15),
),
mainPanel(
plotOutput(outputId = "ma1", width = "700px",height = "400px"))
))
library(shiny)
library(ggplot2)
library(forecast)
library(TTR)
shinyServer(function(input, output){
output$ma1 <- renderPlot(
tmp <- data.frame(time = 1:100, sales = round(runif(100, 150, 879))),
sm <- SMA(tmp[,"sales"],order=input$ord),
y <-ggplot(tmp, aes(time, sales)) + geom_line() + geom_line(aes(time,sm),color="red") + xlab("Days") + ylab("Sales Quantity")+ ggtitle("Moving Average"),
y
)
})
How is this:
library(shiny)
library(ggplot2)
library(forecast)
library(TTR)
ui <- pageWithSidebar(
headerPanel("Forecasting Methods"),
sidebarPanel(
h3(strong("Moving Average",style = "color:black")),
br(),
sliderInput("ord","Order Size:",min = 1, max = 100, step= 1, value = 15)
),
mainPanel(
plotOutput(outputId = "ma1", width = "700px",height = "400px"))
)
server <- function(input, output){
n <- 0
output$ma1 <- renderPlot({
input$ord
tmp <- data.frame(time = 1:100, sales = round(runif(100, 150, 879)) )
sm <- SMA(tmp[,"sales"],order=input$ord)
title <- sprintf("Moving Average (%d)",n)
n <<- n+1
y <-ggplot(tmp, aes(time, sales)) +
geom_line() +
geom_line(aes(time,sm),color="red") +
xlab("Days") + ylab("Sales Quantity")+ ggtitle(title)
y
})
}
shinyApp(ui, server)
Yielding:
As to your program - I could not reproduce your errors exactly:
1 - the program as posted would not run. The server function code block was not enclosed in curly brackets ({}), but was structured like the ui function code (comma separated statements). This is wrong. The ui function code not a function like the server code, rather it series of function calls that output html/css/javascript. Try them from the R-console to see what I mean.
2 - the UI function had at least one extraneous comma that I had to get rid of in order for it to work.
3 - using input$ord in the output$ma1 code that initializes the sm dataframe was not enough to cause the function to be reactive, and be triggered on every update of the slider. Not sure why that was not enough, but when I added another instance of input$ord to the front of the function it worked.
4- I also put a counter in the title of the output$ma1 to help me debug the above-debugged lack of reactivity.
5 - I also combined both the shiny ui.R and server.R files into one file as this example is small and makes it easy to see everything at once. Note that it can be hard matching ui.R and server.R code with the Rstudio tabbed editor - it is worth getting another editor (like Atom or Notepad++) to help code if you need more than one file.

Resources