how to manipulate dataframe in R shiny app - shiny

Please I need assistant concerning a shiny code. I want to manipulate a data frame input by separating them into column vector for computation but I keep getting this error
Warning in <reactive>(...): NAs introduced by coercion
the code is as follows
library(shiny)
ui <- fluidPage(
# dataset
data <- data.frame(e1 = c(3, 7, 2, 14, 66),
e2 = c(2, 16, 15, 66, 30),
n1 = c(18, 25, 45, 62, 81),
n2= c(20, 30, 79, 64, 89))
# Application title
titlePanel("Demo"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
# Input: Upload file
fileInput(inputId = 'file', label = 'upload the file')
),
# Display Output
mainPanel(
uiOutput("final")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
# separating the dataframe into 4 column vectors
e1 <- reactive(as.numeric(input$file[,1]))
e2 <- reactive(as.numeric(input$file[,2]))
n1 <- reactive(as.numeric(input$file[,3]))
n2 <- reactive(as.numeric(input$file[,4]))
# File Upload function
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file = file1$datapath, sep = ',', header = TRUE)
})
output$result <- renderUI({
y <- (e1()/n1()) - (e2()/n2())
lg_y <- log(y)
v2 <- ((n1() - e1())/e1() * n1()) + ((n2() - e2())/e2() * n2())
w <- 1/v2
w1 <- sum(w)
w2 <- sum(w^2)
c <- w1 - (w2/w1)
s2 <- w * lg_y
ybar <- sum(s2)/sum(w)
Q <- sum(w*((lg_y - ybar)^{2}))# Cochrane homogeneity test statistic
Q.pval <- reactive(pchisq(Q, k() - 1,lower.tail = FALSE))
Isqd <- max(100*((Q-(k()-1))/Q),0)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I have searched almost every question on this forum and haven't seen where the question was answered. please I look forward to your help

Still can't run the code above because you don't define function k(). Also FYI, your renderUI is set for "result" but your uiOutput is set for "final".
You get the warning Warning in <reactive>(...): NAs introduced by coercion because your true data set probably includes a non-numeric in it. I did not get any issues with the data set you provided above.
There are a couple ways forward:
1) Write a function to remove all non-numerics before you process the data. See here for a few examples.
2) Just keep the warning, it is a warning after all so it won't stop your code from running. Currently it turns your non-numerics into NA
3) Use suppressWarnings() but that is usually not recommended.
I do have a suggestion to clean up your code though:
# File Upload function
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file = file1$datapath, sep = ',', header = TRUE, stringsAsFactors = FALSE)
})
# separating the dataframe into 4 column vectors
e1 <- reactive(as.numeric(data()[,1]))
e2 <- reactive(as.numeric(data()[,2]))
n1 <- reactive(as.numeric(data()[,3]))
n2 <- reactive(as.numeric(data()[,4]))

Related

How to provide metadata values from server to ui method in shiny

I'm very new to shiny and butting against something there must be a pattern for, but have had no luck Googling.
I have a simple shiny file (app.R below) that returns a plot for n observations. In addition to making the plot available to the ui method, I'd like to pass it n to help it size the plot to my liking
library(shiny)
server <- function(input, output) {
output$distPlot <- renderPlot({
firstNames <- c("Bob", "Jane", "Bob")
lastNames <- c("Builder", "Gorillas", "Weave")
ages <- c(25, 26, 27)
df <- data.frame(firstNames, lastNames, ages)
# I want to pass this to `ui`
numFirstNames <- length(unique(df$firstNames))
mapping <- aes(x = firstNames, y = ages)
ggplot(df, mapping) + geom_violin() + coord_flip()
})
}
getHeightInPx <- function(numFirstNames) {
paste(100 * numFirstNames, "px", sep="")
}
ui <- fluidPage(
# I want height to be a function of numFirstNames as calculated in the server definition
mainPanel(plotOutput("distPlot", height = getHeightInPx(2)))
)
shinyApp(ui, server)
Since ui isn't a function and doesn't have direct access to output (to me it's getting to distPlot by framework magic) how can I get to data prepared in server to help layout the page?
Thanks
https://github.com/rstudio/shiny/issues/650 tipped me off that you could use the height parameter in renderPlot. So I combined that with some use of reactive and observe to call a function that returns the plot AND gives me the number of elements to use.
I hardly get reactive and observe, so while it seems to work I would not be surprised to hear that I am abusing them or that there's an easier way.
library(shiny)
renderDistPlot <- function(input) {
firstNames <- c("Bob", "Jane", "Bob", "Carol")
lastNames <- c("Builder", "Gorillas", "Weave", "Xmasing")
ages <- c(25, 26, 27, 23)
df <- data.frame(firstNames, lastNames, ages)
# I want to pass this to `ui`
numFirstNames <- length(unique(df$firstNames))
mapping <- aes(x = firstNames, y = ages)
plot <- ggplot(df, mapping) + geom_violin() + coord_flip()
list(Plot = plot, NumFirstNames = numFirstNames)
}
server <- function(input, output) {
renderDistPloatResult <- reactive(renderDistPlot(input))
observe(output$distPlot <- renderPlot(renderDistPloatResult()$Plot, height = renderDistPloatResult()$NumFirstNames * 100))
}
ui <- fluidPage(
# I want height to be a function of numFirstNames as calculated in the server definition
mainPanel(plotOutput("distPlot"))
)
shinyApp(ui, server)

Display a subset of a data frame in a Shiny app

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())
})
}

Dynamic anova in Shiny app, is my input wrong?

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
})

To write a csv after the the modaldialogue is closed in shiny

I want to perform some actions like writing in a dataframe post i close the modaldialogue. Consider below example.
obs8<-observe({ req(input$Continue) if(input$password3 > 0 & input$password4 > 0 & (input$password3==input$password4)==TRUE & (is.validpw(input$password3))==TRUE & (is.validpw(input$password4))==TRUE){
showModal(modalDialog(
title=tags$h4(tags$strong("Password Changed Successfully")),
easyClose=FALSE,
footer=modalButton("Close")
))
I am trying to execute below code post the if condition is true and modal is displayed but no luck.
PASSWORD$Passord <- as.character(PASSWORD$Passord)
PASSWORD$Passord[PASSWORD$Passord==pwd] <- input$password3
PASSWORD$Passord <- as.factor(PASSWORD$Passord)
write.csv(PASSWORD,"<PATH>",row.names=FALSE)
I rewrote it as pure Shiny without all the password stuff and it works fine:
ui <- fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
obs8<-observe({
req(input$bins)
if(input$bins > 40){
showModal(modalDialog(
title=tags$h4(tags$strong("Password Changed Successfully")),
easyClose=FALSE,
footer=modalButton("Close")
))
write.csv("1, 2, 1, 2", "<PATH>", row.names = FALSE)
}
})
}
# Run the application
shinyApp(ui = ui, server = server)
There's something wrong with the other stuff you're doing, but I can't tell what it is without a reproducible example

interactive correlation heatmap in shiny

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: