Sorry if this question has been asked before, but I haven't quite found exactly what I was looking for by searching around.
I'm working on a small app to bring in scores from a debate activity and have those scores plotted in a scatterplot. I've figured out how to actually make the plot, but getting the data into it is a separate story.
I have all of my inputs as a numericInput with a unique input ID, but I haven't had any luck putting that data into its own frame.
I tried making a few different sets and then compiling all of those into one frame (using name1<-c(x, y z), name2<-c(a,b,c)... and then frame<-as.matrix(c(name1,name2....)) but it tells me that I'm attempting to do something that requires a reactive context.
If anyone knows how I could make my numericInputs drop into a dataframe, that would be lovely.
EDIT: I think I'm looking to make a reactive data table, but I'm not entirely sure. Again, any suggestions will be greatly appreciated!
Given the description of your problem, which is not that clear and do not show exactly what you need, this is what I recomment:
An app which takes 6 numerics inputs, combine all in a data frame with two columns and create a scatter plot with that data.
library(shiny)
library(ggplot2)
library(dplyr)
# 1 - The UI with a sidebar layuot
ui <- fluidPage(
sidebarLayout(
# A well panell to separate the values
# for the X axis
sidebarPanel = sidebarPanel(
wellPanel(
h3("X axis"),
numericInput('numb1', 'A', value = 1),
numericInput('numb2', 'B', value = 2),
numericInput('numb3', 'C', value = 3)
),
# A well panell to separate the values
# for the Y axis
wellPanel(
h3("Y axis"),
numericInput('numb4', 'A', value = 1),
numericInput('numb5', 'B', value = 2),
numericInput('numb6', 'C', value = 3)
)),
# Main panel with the plot
mainPanel = mainPanel(
plotOutput("plot")
)
)
)
server <- function(input, output, session) {
# Here You create a reactive objece with all the values
data <- reactive({
data.frame(
a = c(input$numb1, input$numb2, input$numb3),
b = c(input$numb4, input$numb5, input$numb6)
)
})
# plot output
output$plot <- renderPlot({
data() %>%
ggplot(aes(x = a, y = b)) +
geom_point()
})
}
shinyApp(ui, server)
Let me know if this is it
Related
library(shiny)
library(palmerpenguins)
library(ggplot2)
library(dplyr)
penguin <- penguins
penguin$year <- as.factor(penguin$year)
ui <- fluidPage(
titlePanel("Data Visualisation of Penguins Data"),
sidebarPanel(
selectInput("yaxis",
label = "Choose a y-axis variable to display",
choices = list("bill_length_mm",
"bill_depth_mm",
"flipper_length_mm",
"body_mass_g"),
selected = "bill_length_mm"),
selectInput("xaxis",
label = "Choose a x-axis variable to display",
choices = c("species",
"sex",
"year"),
selected = "sex"),
checkboxGroupInput("islandlevels",
label = "Check to display different island levels",
choices = c("island"),
selected = NULL),
br(), br(),
selectInput("species",
label = "Choose species to view separate plot",
choices = list("Adelie",
"Chinstrap",
"Gentoo"),
selected = NULL)),
mainPanel(
plotOutput("plot1"),
br(), br(),
plotOutput("plot2")
)
)
server <- function(input, output){
output$plot1 <- renderPlot({
if(is.null(penguin))
return(NULL)
ggplot(penguin, aes(x = penguin[[input$xaxis]], y = penguin[[input$yaxis]])) +
geom_boxplot()
})
}
shinyApp(ui = ui, server = server)
This is my shiny code, but I'd like to remove NA value when x-axis variable is sex.
I can't just remove row with NA values because I have to use variable (that is not missing value but the row has missing value such as row 9 in image 2) when I change x-axis variable or/and y-axis variable.
I wanted to find the solution but I wonder what function should I use. Do I have to use if statement, reactive function, or else?
Thank you for help in advance.
sex variable with NA value(want to delete NA on my plot)
You can prevent the NA values of showing up as categories by making use of scale_x_discrete(na.translate = FALSE):
library(ggplot2)
library(palmerpenguins)
ggplot(penguins, aes(x = sex, y = bill_length_mm)) +
geom_boxplot() +
scale_x_discrete(na.translate = FALSE)
#> Warning: Removed 11 rows containing missing values (stat_boxplot).
Conditionally filter your data, perhaps something like this:
dat <- reactive({
if (input$xaxis == "sex") penguin[ !is.na(penguin$sex), ] else penguin
})
output$plot1 <- renderPlot({
req(penguin, input$xaxis, input$yaxis)
ggplot(dat(), aes_string(x = isolate(input$xaxis), y = input$yaxis)) +
geom_boxplot()
})
Several critical changes here:
In case you want to do more than a single plot with the filtered data, I make a reactive data component named dat with the filtered data. In this way, if you ever add (say) a table or another plot or something, you don't need to handle selective filtering in each of them, you just need to use dat() everywhere and everything benefits from it.
Reactive can be volatile, and having both the data and the plot reacting to input$xaxis will cause the plot to be rendered twice for each change to xaxis. Because of this, I isolate(input$xaxis) in the plot reactive. When the user changes xaxis, the dat will change which will trigger (once!) the plot to change. (No need to isolate yaxis, as that's correct in this case.)
In general, you should not use ggplot2(x, aes(x$a, x$b)). More specifically, using $ and/or [[ in aesthetic definitions is poor practice, and will fail given certain situations. It is much better to use aes with symbols (e.g., cyl from mtcars) or aes_string with strings ("cyl"). Since you're defining the aesthetics programmatically, it is better to use aes_string.
I changed your if (is.null(penguin)) to shiny's more canonical req, and added checks in the inputs as well. While most simpler shiny apps don't always need this, I've found that more complex apps can cause just enough delay in input instantiation that an output reactive block may trigger before all inputs have been assigned, meaning in this example it might be possible for input$xaxis to be null. While unlikely in simpler shiny apps like this, I still think it's safe.
There may be reasons to use individual req lines, one for each input. The results in this case will be the same, but there are times when it makes sense to break them out.
The use of req prohibits the rest of the plot rendering from occurring, but it also does it in a way that shiny components recognize, not causing errors or rendering issues. (I prefer it to manual if (is.null(.)) return(NULL) logic.)
Note: I think #stefan's answer may be the more canonical way in ggplot2 to omit NA values from the axis, so perhaps that is the best way to go for that side of things. However, I still believe that points 3 and 4 are still (also) relevant to your app even with stefan's change.
I'm trying to create a Shiny app that lets users
create a dataset by entering frequency counts for different values
plot a histogram of that dataset
A paired back example of the code is as follows:
library(shiny)
library(ggplot2)
# Define UI for application
ui <- fluidPage(
# Sidebar with inputs
sidebarLayout(
sidebarPanel(
numericInput("data1s",
"How many have a score of 1?",
value = 0,
min = 0
),
numericInput("data2s",
"How many have a score of 2?",
value = 0,
min = 0
),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 3,
value = 1)
),
# Show a plot of the data
mainPanel(
htmlOutput("mydatatable"),
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
#show the data
output$mydatatable <- renderTable({
#create the dataframe from the frequncies
mydata <- data.frame(our_data=c(rep(1,input$data1s),rep(2,input$data2s))
)
}
)
#show the histogram
output$distPlot <- renderPlot({
ggplot(mydata, aes(x=our_data)) +
geom_histogram(bins = input$bins)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I have achieved the creation of the dataset, but the code for displaying a histogram of the data returns an error: "object 'mydata' not found" instead of showing the histogram. The histogram should update whenever any of the inputs are changed.
Any help to resolve would be much appreciated.
The mydata that you define in the mydatatable reactive is not visible anywhere else. To understand why, I suggest you read about R's namespaces and environments; one good tutorial on it is Hadley's Advanced R -- Environments.
To fix it, I suggest you make the data itself a reactive block, and depend on it in your two other blocks (table and plot):
server <- function(input, output) {
mydata <- reactive({
req(input$data1s, input$data2s)
data.frame(our_data=c(rep(1,input$data1s),rep(2,input$data2s)))
})
#show the data
output$mydatatable <- renderTable({ req(mydata()); })
#show the histogram
output$distPlot <- renderPlot({
req(mydata())
ggplot(mydata(), aes(x=our_data)) +
geom_histogram(bins = input$bins)
})
}
(Untested.)
I added the use of req solely to prevent start-up jittering and warnings/errors in the app. When the shiny app is warming up, it's common to have input variables empty (NULL), and things that depend on it will temporarily produce errors until the inputs stabilize. (For an example of why things will stumble, input$data1s may initially show a NULL value, and try to see if data.frame(our_data=rep(1,NULL)) will work.)
req just looks for something that is "truthy", meaning: not NULL, not NA, not FALSE, length greater than 0, etc. See ?shiny::req for more details.
While req is not strictly required, it has its advantages. As you may infer from the table code, req(x) will return the "first value that was passed in" (from ?req), so it can be used in this shortcut mode for brevity.
And one last soap-box: in my limited experience with shiny reactivity, there are few times that I've generated data within a reactive block and used it solely within that reactive block. Given that, whenever you make a data.frame (or list or ... some important structure that is dependent on user input), it is often beneficial to make it its own reactive component (specifically, not an output component), and then depend on it as many times as necessary.
I have been creating a data viewer app using shiny and plotly. I want to make a create a multi dimensional scaling view of my data, and then click on a data point to be able to view the individual point as a barplot. I was inspired by this example.
Here is a minimal almost working example:
The ui.r file
library(shiny)
library(mlbench)
library(plotly)
library(shinythemes)
library(dplyr)
# Load the data
allDat <- iris[,-5]
# ui.R definition
ui <- fluidPage(
# Set theme
theme = shinytheme("spacelab"),
# Some help text
h2("Inspect each element in iris data set"),
h4("This a shiny app exploiting coupled events in plotly"),
tags$ol(
tags$li("The first chart showcases", tags$code("plotly_click"))
),
# Vertical space
tags$hr(),
# First row
fixedRow(
column(6, plotlyOutput("Plot1", height = "600px")),
column(6, plotlyOutput("Plot2", height = "600px"))),
tags$hr())
The server.r file
# server.R definition
server <- function(input, output){
d <- dist(allDat) # euclidean distances between the rows
fit <- cmdscale(d,eig=TRUE, k=2) # k is the number of dim
# plot solution
x <- fit$points[,1]
y <- fit$points[,2]
plot.df <- data.frame(x=x,y=y,allDat)
output$Plot1 <- renderPlotly({
plot_ly(plot.df, x = x, y = y, mode="markers", source = "mds") %>%
layout(title = "MDS of iris data",
plot_bgcolor = "6A446F")
})
# Coupled event 2
output$Plot2 <- renderPlotly({
# Try to get the mouse click data
event.data <- event_data("plotly_click", source = "mds")
# If NULL dont do anything
if(is.null(event.data) == T) return(NULL)
# I need the row of the data in the allDat data frame
# pretty sure this is not correct
ind <- as.numeric(event.data[2])
p1 <- plot_ly(x = colnames(allDat), y=as.numeric(allDat[ind,]),type="bar")
})
}
To run this, put these two files in a folder called something, e.g. dataViewer, then run runApp("dataViewer") from the directory that contains the dataViewer folder.
What is the question and what am I seeking?
I do not understand the output that comes from the event_data function. I want to be able to click on a point on the scatter plot and extract the row number of that data point from the allDat data frame, or the plot.df data frame, because it should be the same. Then I want to use that row number to further visualize that specific point in the barplot on the right.
I looked into the event.data object, and think the value you are looking for is event.data$pointNumber (which starts with 0 so you need to use event.data$pointNumber + 1 to identify the line).
event.data is a list with four names: curveNumber, pointNumber, x and y.
I want to use the functionality of nearPoints() to print out summary statistics for a specific point without printing the x, y associated with that point. I have been able to use this function printing the data frame and variations of the data frame. Is there anyway to suppress those columns
to customize the output? nearPoints comes from the latest version of shiny 0.12.1 but I believe may have been introduced a little earlier.
I know the documentation says this:
Note that these functions are only appropriate if the x and y variables are present in the data frame, without any transformation. If, for example, you have a plot where a the x position is calculated from a column of data, then these functions won’t work. In such a case, it may be useful to first calculate a new column and store it in the data frame.
but wanted to know if there was any kind of work around.
Here is the app that illustrates this problem, note that I'm using all of those libraries in my bigger app:
library(shiny)
library(ggplot2)
library(Cairo)
library(plyr)
library(dplyr)
library(shinydashboard)
library(grid)
library(gridExtra) # also loads grid
library(grDevices)
library(ggmap)
library(sqldf)
cars <- mtcars
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
dataTableOutput("info")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
ggplot(cars, aes(x=cyl, y=carb)) + geom_point()
})
output$info <- renderDataTable({
summary_cars <- ddply(cars, .(gear, cyl, carb),
function(dd){as.data.frame(cbind(Mean_hp = mean(dd$hp),
Mean_wt = mean(dd$wt))
)
})
#This works-------------------------------------------------------
# nearPoints(summary_cars, input$plot_click, threshold = 10,
# addDist = TRUE)
#Removing the columns does not work ---------
nearPoints(select(summary_cars,-cyl,-carb), input$plot_click, threshold = 10,
addDist = F)
})
}
shinyApp(ui, server)
I'm designing an R program to output different graphs of any csv file input. I am using Rstudio Shiny and ggplot2 to develop the program.
My problem involves ordering dates chronologically rather than alphabetically (which is the default apparently). Let's use this code as an example (my code is a bit different, but this is code from someone who helped me earlier):
related posts:
Unable to change the graph form of my ggplot rshiny program, help me find the bug?
Sorting months in R
How do you order a nominale variable. e.g month in R?
Boxplot with ggplot2 in R - returns by month
server.R
library(shiny)
library(datasets)
library(ggplot2)
X <- read.csv(file.choose())
# Define server logic required to summarize and view the selected dataset
shinyServer(function(input, output) {
output$opt.x <- renderUI({
selectInput("xcolumn", "X column to Plot",
names(Y())
)
})
output$opt.y <- renderUI({
selectInput("ycolumn", "Y Column",
names(Y()))
})
# Generate a summary of the dataset
output$summary <- renderPrint({
dataset <- X
summary(dataset)
})
# Show the first "n" observations
output$view <- renderTable({
head(X, n = input$obs)
})
createPlot <- function(df, colx, coly) {
p <- ggplot(data=df, aes(x=df[,colx],y=df[,coly]), environment = environment()) #+ geom_line(aes(x=df[,colx],y=df[,coly], group=colx))
p <- p + geom_line(aes(group=colx))
p <- p + xlab(names(df)[colx]) + ylab(names(df)[coly])
}
Y <- reactive({
X
})
# create a basic plot
output$plotBasic <- reactivePlot(function() {
df <- Y()
print(createPlot(df, colx=input$xcolumn, coly=input$ycolumn))
})
})
ui.R
library(shiny)
# Define UI for dataset viewer application
shinyUI(pageWithSidebar(
# Application title
headerPanel("My app!"),
# Sidebar with controls to select a dataset and specify the number
# of observations to view
sidebarPanel(
numericInput("obs", "Number of observations to view:", 13),
uiOutput("opt.x"), #dynamic UI
uiOutput("opt.y") #value comes from Server.R
),
# Show a summary of the dataset and an HTML table with the requested
# number of observations
mainPanel(
tabsetPanel(
tabPanel("Table", tableOutput("view")),
tabPanel("BasicGraph", plotOutput("plotBasic"))
)
)
))
This can be taken care of easily with factor or as.Date functions if you started with a list that you knew of, but here I am taking in input (can assume the format is mm-yyyy) and I do not know how to set the column of x variable data to a variable. This is because the user can choose any column in the imported data as the X column.