New to Shiny, I am trying to create a very simple app respecting the following sequence of events:
(1) Upload a dataframe,
(2) Wait until the user set the filtering parameter (Category in the example below),
(3) Press a Go! button,
(4) Display the first rows of the subset data frame.
Let's say I have a file df.tab to upload and process.
df <- data.frame(Category=c("A","A","A","B","B","B"), X=c(1,2,3,1,2,3), Y=c(1,2,3,34,21,1))
df
Category X Y
1 A 1 1
2 A 2 2
3 A 3 3
4 B 1 34
5 B 2 21
6 B 3 1
write.table(df, file="df.tab", row.names=F, quote=F, sep="\t")
My app.R looks like:
library(shiny)
# Define UI ----
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("input_df",label=h4("Dataset")),
selectInput("category",h4("Category"), choices = list("A" = 1,"B" = 2),selected = 1),
actionButton("goButton",label = "Go!")
),
mainPanel(
tableOutput("view")
)
)
)
# Define server logic ----
server <- function(input, output) {
data <- eventReactive(
input$input_df,
{
File <- input$input_df
if(is.null(File)){
return(NULL)
}else{
df <- read.table(File$datapath, header = T, sep = "\t")
}
}
)
data_sub <- eventReactive(
input$category,
{
df_sub <- subset(data(), Category == input$category)
}
)
output$view <- renderTable(
{
head(data_sub())
}
)
}
# Run the app ----
shinyApp(ui = ui, server = server)
However, the app is either not responsive or does not display any rows.
Note that I created 2 distinct reactive events data and data_sub in order to avoid loading the file every time I select a different category (and potentially to avoid stack errors with a recursive function).
Any help would be greatly appreciated.
Here is a working server function. Use reactive, not eventReactive and it is quite straightforward.
NOTE that your example assumes you have a Category column, I modified below to make it work with anything.
# Define server logic ----
server <- function(input, output) {
dataset <- reactive({
File <- input$input_df
req(File)
read.table(File$datapath, header = TRUE, sep = "\t")
})
data_sub <- reactive({
if("Category" %in% names(dataset())){
subset(dataset(), Category == input$category)
} else {
dataset()
}
})
output$view <- renderTable({
head(data_sub())
})
}
Related
I am creating a Shiny application and when I am debugging with the browser() function I have errors with the if-statement
For example, if I write this (complete example below):
if(1 < 2)
{
h <- 5
}
And I receive this:
debug at #3: h <- 5
What could be wrong? It looks that if-statment doesn't work inside the browser.
Thanks
library(shiny)
# Global variables can go here
n <- 200
# Define the UI
ui <- bootstrapPage(
numericInput('n', 'Number of obs', n),
plotOutput('plot')
)
# Define the server code
server <- function(input, output) {
browser()
if(1 < 2)
{
h <- 5
}
output$plot <- renderPlot({
hist(runif(input$n))
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
data(mtcars)
library(stats)
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
selectizeInput("mtcarsid", "Nehme eine MT Cars category.", choices = colnames(mtcars), selected = colnames(mtcars)[2], multiple = FALSE)
),
# Show a plot of the generated distribution
mainPanel(
tableOutput("model"),
textOutput("text123")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$text123 <- renderText({
})
output$model <- renderTable ({
z <- factor(input$mtcarsid)
# #print(mtcars[[z]])
#
# print(length(mtcars$mpg))
#
# print(length(mtcars[[z]]))
x <- aov(mpg ~ factor(mtcars[[z]]), data=mtcars)
x <- TukeyHSD(x)
print(x)
x <- as.data.frame(x[[1]][,4] > 0.05)
x
})
}
# Run the application
shinyApp(ui = ui, server = server)
This is my App and based on the input of my input$mtcarsid I want to perform an anova incl. a post-hoc test. However, my model seems to totally wrong input with my code. Can anybody tell me why?
aov(mpg ~ factor(cyl), data = mtcars)
This code works fine. But when i just use factor(input$mtcarsid) i get an error that length of input differs (1 vs 32).
One solution is to convert the selected variable to a factor outside of the call to aov().
output$model <- renderTable ({
mtcars[["selected"]] = factor(mtcars[[input$mtcarsid]])
x <- aov(mpg ~ selected, data=mtcars)
x <- TukeyHSD(x)
print(x)
x <- as.data.frame(x[[1]][,4] > 0.05)
x
})
I am developing a table which does some calculations each time that an action button is used. One column of my table depends on its previous value,
C_new <- C_old + B_new - A_new
For instance, if A=4, B=A+2 and C= C(-1) + B - A my expected results are
A B C
1 2 3
4 6 5
I have tried to save the previous value of column C using reactiveValue, as mentioned in How to “remember” information from the previous iteration when using reactiveTimer in Shiny?, but it doesn't work. I don't know where I am getting wrong.
Here is my code
library(shiny)
ui <- fluidPage(
sidebarPanel(textInput("c1","Example"),
actionButton("update", "Update Table")),
mainPanel(tableOutput("example"))
)
server <- function(input, output) {
C_old <- reactive(x=3)
values <- reactiveValues(df = data.frame(A=1, B=2, C=3))
newEntry <- observeEvent(input$update,{
A_new <- as.numeric(input$c1)
B_new <- A_new + 2
C_new <- isolate (C_old$x + B_new - A_new)
C_old$x <<- C_new
new <- data.frame(A=A_new,B=B_new, C=C_new)
# attach the new line to the old data frame here:
values$df <- rbind(values$df, new)
})
# Print the content of values$df
output$example <- renderTable({
return(values$df)
})
}
shinyApp(ui = ui, server = server)
Important to know, observeEvents (similar to observes) don't have outputs. You just observe a change and do something in their body, but nothing is supposed to be returned (this is different to reactive({ }), which also observes changes but has return values), useful link.
Isolate is not needed in observeEvent , because nothing triggers an update except for input$update (this is different to observe and reactive, where all changeable items in the body trigger an update).
Below is the solution to your problem. I used reactiveVal which stores one single updateable value (see ?reactiveVal for help). After clicking the action button, I retrieve the old table by calling values(), calculate all new values (beware, I need to use tail to get only the last C value) and attach the result to the old value before storing the extended table into values by calling values(new_df):
library(shiny)
ui <- fluidPage(
sidebarPanel(numericInput("c1","Example", 0),
actionButton("update", "Update Table")),
mainPanel(tableOutput("example"))
)
server <- function(input, output) {
# stores the current data frame, called by values() and set by values(new_data_table)
values <- reactiveVal(data.frame(A=1, B=2, C=3))
# update values table on button click
observeEvent(input$update,{
old_values <- values()
A_new <- input$c1
B_new <- A_new + 2
C_new <- tail(old_values$C, 1) + B_new - A_new # tail to get the last C value
new_values <- data.frame(A=A_new, B=B_new, C=C_new)
# attach the new line to the old data frame here:
new_df <- rbind(old_values, new_values)
#store the result in values variable
values(new_df)
})
# Print the content of values$df
output$example <- renderTable({
return(values())
})
}
shinyApp(ui = ui, server = server)
I want to reproduce the example at: https://scip.shinyapps.io/scip_app/
Basically, I have a 300 by 300 adjusted correlation matrix and a 300 by 300 unadjusted correlation matrix and want to show them interactively with zoom in and zoom out function. The text descriptions should display the point estimates and confidence intervals.
Is there any template I can quickly refer to?
Building on the data from Mike, you can use the d3heatmap library
library(d3heatmap)
library(shiny)
n1 <- 100
n2 <- 100
nr <- 30
nc <- 30
set.seed(1)
x <- matrix(rnorm(n1), nrow=nr, ncol=nc)
y <- matrix(rnorm(n2), nrow=nr, ncol=nc)
MAT <- cor(x,y)
ui <- fluidPage(
mainPanel(
d3heatmapOutput("heatmap", width = "100%", height="600px")
)
)
## server.R
server <- function(input, output) {
output$heatmap <- renderD3heatmap({d3heatmap(MAT)})
}
shinyApp(ui = ui, server = server)
Edit: Specify the colours if needs to be and display the data as is, note that Colv = T by default, which means it will group the correlated items together
output$heatmap <- renderD3heatmap({d3heatmap(MAT, colors = "Blues", Colv = FALSE)})
I think plotly can do this well. Here are the docs https://plot.ly/r/heatmaps/:
And here is a little template-example (returning Porkchop's favor by borrowing his minimal shiny template) with some fake data:
library(shiny)
n1 <- 100
n2 <- 100
nr <- 30
nc <- 30
set.seed(1)
x <- matrix(rnorm(n1), nrow=nr, ncol=nc)
y <- matrix(rnorm(n2), nrow=nr, ncol=nc)
cmat <- cor(x,y)
plot_ly(z = cmat, type = "heatmap")
ui <- fluidPage(
mainPanel(
plotlyOutput("heatmap", width = "100%", height="600px")
)
)
## server.R
server <- function(input, output) {
output$heatmap <- renderPlotly({plot_ly(z = cmat, type = "heatmap")})
}
shinyApp(ui,server)
Here is the Shiny output. Note it is fully zoomable:
A txt.file data contaning a matrix of integers with 5 integers for each column and 1000 rows.
So if we press
data
we get this output
96520
69850
...
36884
We can get a random row by this
getnumbers <- sample(data,1, replace=FALSE)
By getting a random row in data the task is to enter the next row (by press a,b,c,d,e) and check if it's correct. So if we have the kth entry in data we want to get the k+1 entry in data by pressing the digits and see if it's correct.
check <- function(a,b,c,d,e){
if( identical( data[k+1] , c(a,b,c,d,e)) == TRUE ) {
return("Correct") }
else{return("Not correct")}
How can I implement this R code in Shiny so I can make it interactive using ubuntu ?
Hopefully I understood your question correctly but here's how you could do it:
library(shiny)
data <- matrix(round(runif(5*3)),ncol=3)
ui <- shinyUI(fluidPage(
fluidRow(
column(6, h4("Randomly Selected Row [k]")),
column(6, h4("Nex Row [k+1]"))
),
fluidRow(
column(6, textOutput("selRow")),
column(6, textOutput("nxtRow"))
),
fluidRow(
column(8, textInput("guessStr","Gues row: ")),
column(4, actionButton("guess","guess"))
),
textOutput("guessRes")
))
server <- shinyServer(function(input, output, session) {
# Make the current rownumber a reactive
r.num <<- 0
makeReactiveBinding('r.num')
# If rownumber changes update UI
observe({
if(is.null(r.num)) return(NULL)
output$selRow <- renderPrint({data[r.num,]})
output$nxtRow <- renderPrint({data[r.num+1,]})
})
# Get a row number by random, can't select last row
randomRow <- function(){
r.num <<- sample(1:nrow(data)-1, 1)
}
# If user presses guess button
observeEvent(input$guess, {
# I convert to numerical but this can be modified to work with characters to
input.str <- as.numeric(strsplit(input$guessStr,',')[[1]])
msg <- sprintf("You guessed that the next row is: %s",input$guessStr)
if( identical(data[r.num+1,], input.str)){
msg <- paste(msg," , this was correct!")
}
else{
msg <- paste(msg," , this was wrong")
}
output$guessRes <- renderPrint({msg})
})
# Initiate the guessing by randmozing a row
randomRow()
})
shinyApp(ui = ui, server = server)