I am begginer in shiny an I am stucked adding feedback in my app.
I have tried a few things like write this code inside the eventReactive function like use the function feedBackDanger.
Below, there is a simplified full code with the ui, the idea is that i need the user get some Error (but not the console Error) if he set 'zero' in kind variable when mean is 3,6 or 9.
Also the actionButton 'simulate' should be disable when this condition is selected.
ui <- shinyUI(fluidPage(
titlePanel(h1("Simulation", align = 'center')),
sidebarLayout(
sidebarPanel(
numericInput(inputId = "n", label = "Size of Sample", min = 1,
step = 1, value = 1),
numericInput(inputId = "mean", label = "Mean of Sample", min = 1,
step = 1, value = 1),
numericInput(inputId = "var", label = "Variance", min = 1,
step = 0.25, value = 1),
radioButtons("kind", "Sample kind", choices = c("two", "zero")),
actionButton("simulate", "Simulate"),
width = 200
),
mainPanel(
plotOutput("distPlot", width = 500, height = 500)
)
)
))
# Define server logic required to draw a histogram
server <- shinyServer(function(input, output, session) {
s_fin <-function(n,
mean,
var,
kind){
a <- rnorm(n, mean, var)
if(kind == 'two'){
a <- a + 2
}
if(kind == 'zero'& mean %in% c(3,6,9)){
print('ERROR: function error')
stop(call. = T)}
return(a)
}
simulation <- eventReactive(input$simulate,{
s_fin(n = input$n,
mean = input$mean,
var = input$var,
kind = input$kind)
})
output$distPlot <- renderPlot({
hist(simulation())
})
})
shinyApp(ui, server)
The next code works to me (a just add useShinyFeedback() in ui.R, and put the error function instead of print):
library(shinyFeedback)
ui <- shinyUI(fluidPage(
useShinyFeedback(),
titlePanel(h1("Simulation", align = 'center')),
sidebarLayout(
sidebarPanel(
numericInput(inputId = "n", label = "Size of Sample", min = 1,
step = 1, value = 1),
numericInput(inputId = "mean", label = "Mean of Sample", min = 1,
step = 1, value = 1),
numericInput(inputId = "var", label = "Variance", min = 1,
step = 0.25, value = 1),
radioButtons("kind", "Sample kind", choices = c("two", "zero")),
actionButton("simulate", "Simulate"),
width = 200
),
mainPanel(
plotOutput("distPlot", width = 500, height = 500)
)
)
))
# Define server logic required to draw a histogram
server <- shinyServer(function(input, output, session) {
s_fin <-function(n,
mean,
var,
kind){
a <- rnorm(n, mean, var)
if(kind == 'two'){
a <- a + 2
}
if(kind == 'zero'& mean %in% c(3,6,9)){
showFeedbackDanger(
inputId = "mean",
text = "Not use mean 3, 6 or 9"
)
shinyjs::disable("simulate")
}else{
hideFeedback("mean")
shinyjs::enable("simulate")
}
return(a)
}
simulation <- eventReactive(input$simulate,{
s_fin(n = input$n,
mean = input$mean,
var = input$var,
kind = input$kind)
})
output$distPlot <- renderPlot({
hist(simulation())
})
})
shinyApp(ui, server)
What I have
I made a Shiny app that shows a plot with some points.
You can manually change the y axis. There is a button that allows to automatically adjust the y axis so it fits the data. There is a drop-down box that allows you to select data.
I have this code:
library(shiny)
# user interface ----------------------------------------------------------
ui <- fluidPage(
fluidRow(plotOutput("myplot")),
tabsetPanel(
tabPanel(
"Input",
fluidRow(
column(
2,
numericInput(inputId = "ymax", label = "y-axis maximum", value = 30),
numericInput(inputId = "ymin", label = "y-axis minimum", value = 9),
actionButton("fity", label = "zoom to fit")
),
column(
2,
selectInput(inputId = "yaxis", label = "y-axis",
choices = list("1 to 5" = 1,
"3 to 7" = 2)
),
checkboxInput("mybx", label = "checkbox", value = TRUE)
)
)
),
fluidRow()
)
)
# server function ---------------------------------------------------------
server <- function(input, output, session) {
ydata <- reactive({
switch(input$yaxis,
"1" = {
updateCheckboxInput(session, "mybx", value = TRUE)
1:5},
"2" = {
updateCheckboxInput(session, "mybx", value = FALSE)
3:7}
)
})
observeEvent(input$fity, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
output$myplot <- renderPlot({
par(mar = c(4, 4, 0.1, 0.1))
plot(x = 1:5, y = ydata(), ylim = c(input$ymin, input$ymax))
})
}
shinyApp(ui = ui, server = server)
What I want to do
I want that the fit-y-axis code triggered by the action button will also be triggered when I'm changing the data with the dropdown box.
Things I've tried:
This. But I think it doesn't like getting a selectInput together with the button.
Putting the fit-y-axis code into a separate function, calling the function from both ydata <- reactive and observeEvent. Did not work. Cries about recursion (obviously - it's calling ydata again from inside ydata!).
Any help would be appreciated.
Why not just have another observeEvent that monitors the change in the yaxis input?
library(shiny)
# user interface ----------------------------------------------------------
ui <- fluidPage(
fluidRow(plotOutput("myplot")),
tabsetPanel(
tabPanel(
"Input",
fluidRow(
column(
2,
numericInput(inputId = "ymax", label = "y-axis maximum", value = 30),
numericInput(inputId = "ymin", label = "y-axis minimum", value = 9),
actionButton("fity", label = "zoom to fit")
),
column(
2,
selectInput(inputId = "yaxis", label = "y-axis",
choices = list("1 to 5" = 1,
"3 to 7" = 2)
),
checkboxInput("mybx", label = "checkbox", value = TRUE)
)
)
),
fluidRow()
)
)
server <- function(input, output, session) {
ydata <- reactive({
switch(input$yaxis,
"1" = {
updateCheckboxInput(session, "mybx", value = TRUE)
1:5},
"2" = {
updateCheckboxInput(session, "mybx", value = FALSE)
3:7}
)
})
observeEvent(input$fity, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
observeEvent(input$yaxis, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
output$myplot <- renderPlot({
par(mar = c(4, 4, 0.1, 0.1))
plot(x = 1:5, y = ydata(), ylim = c(input$ymin, input$ymax))
})
}
shinyApp(ui = ui, server = server)
But this makes your 'zoom to fit' button redundant.
I'm creating a version of a sample size and power calculator. After running the code, when selecting the option "Sample Size", any updates to the sample size are immediate after moving around sliders or other numeric Inputs. However for the option "Power" (both coming from the first "selectInput" option), updates are not immediate if at all occurring.
I'm not sure if the correct move forward is to use a reactive expression.
library(shiny)
library(pwr)
ui <- fluidPage(
titlePanel("Sample Size and Power Calculator"),
sidebarLayout(
sidebarPanel(
#What are we calculating?
selectInput(inputId = "type",
label = strong("Calculator Options"),
choices = c("Pick an Option",
"Power",
"Sample Size"),
selected = "Pick an Option"),
#Display only if Sample Size is selected, ask for necessary parameters
conditionalPanel(
condition = "input.type == 'Sample Size'",
#1. Standard Deviation
numericInput(inputId = "stddev",
label = "Standard Deviation",
value = 10,
min = 1,
max = 400,
step = 1),
#2. Power
sliderInput(inputId = "power",
label = "Power of Study",
min = 0.5,
max = 0.99,
value = 0.8,
step = 0.01),
h6("Power as a decimal not percentage."),
h6("(0.8 means 80% power)"),
#3. Alpha (Significance)
sliderInput(inputId = "alpha",
label = "Significance of Study",
min = 0.01,
max = 0.2,
value = 0.05,
step = 0.01),
h6("Significance of study is most traditionally 0.05 (5%)"),
#4. Meandiff (Difference Between Groups)
numericInput(inputId = "meandiff",
label = "Expected Difference Between Group Means",
value = 20),
#5. Alternative Test
selectInput(inputId = "alt",
label = strong("Alternative Test Options"),
choices = c("Two-Sided" = "two.sided",
"Upper" = "greater",
"Lower" = "less"),
selected = "Two-Sided"),
h6("If unsure, leave at 'Two-Sided'.")
),
#Display only if Power is selected, ask for necessary parameters
conditionalPanel(
condition = "input.type == 'Power'",
#1. Standard Deviation
numericInput(inputId = "stddev",
label = "Standard Deviation",
value = 10,
min = 1,
max = 400,
step = 1),
#2. Size Per Group
numericInput(inputId = "npergroup",
label = "Number per Group",
value = 120),
h6("Assuming equal number in each group, enter number for ONE group."),
#3. Alpha (Significance)
sliderInput(inputId = "alpha",
label = "Significance of Study",
min = 0.01,
max = 0.2,
value = 0.05,
step = 0.01),
h6("Significance of study is most traditionally 0.05 (5%)"),
#4. Meandiff (Difference Between Groups)
numericInput(inputId = "meandiff",
label = "Expected Difference Between Group Means",
value = 20),
#5. Alternative Test
selectInput(inputId = "alt",
label = strong("Alternative Test Options"),
choices = c("Two-Sided" = "two.sided",
"Upper" = "greater",
"Lower" = "less"),
selected = "Two-Sided"),
h6("If unsure, leave at 'Two-Sided'.")
)
),
#Output:
mainPanel(
textOutput(outputId = "intro"),
textOutput(outputId = "desc"),
conditionalPanel(
condition = "input.type == 'Sample Size'",
textOutput(outputId = "samplesize")
),
conditionalPanel(
condition = "input.type == 'Power'",
textOutput(outputId = "power")
)
)
)
)
server <- function(input, output) {
#Introductory Text
output$intro <- renderText({
"Select an option and adjust the sliders and parameters."
})
#Description of what has been chosen
output$desc <- renderText({
paste("You chose: ", input$type)
})
#If Sample Size is selected, what is the sample size
output$samplesize <- renderText({
paste("Sample Size Per Group for Two-Sample t-test for Mean Diff
Assuming Two Groups and Equal Variances: ",
as.character(ceiling(pwr.t.test(d = input$meandiff / input$stddev,
sig.level = input$alpha,
power = input$power,
type = "two.sample",
alternative = input$alt)$n)))
})
#If Power is selected, what is the power
output$power <- renderText({
paste("Power for Two-Sample t-test for Mean Diff Assuming Two Groups and
Equal Variances: ",
format(round(pwr.t.test(d = input$meandiff / input$stddev,
sig.level = input$alpha,
n = input$npergroup,
type = "two.sample",
alternative = input$alt)$power * 100, 2),
nsmall = 2))
})
}
shinyApp(ui = ui, server = server)
It would be ideal that all the input ids are unique. Below I added 2 for those duplicated input ids. All of them are in the power analysis. After this change, the code works.
library(shiny)
library(pwr)
ui <- fluidPage(
titlePanel("Sample Size and Power Calculator"),
sidebarLayout(
sidebarPanel(
#What are we calculating?
selectInput(inputId = "type",
label = strong("Calculator Options"),
choices = c("Pick an Option",
"Power",
"Sample Size"),
selected = "Pick an Option"),
#Display only if Sample Size is selected, ask for necessary parameters
conditionalPanel(
condition = "input.type == 'Sample Size'",
#1. Standard Deviation
numericInput(inputId = "stddev",
label = "Standard Deviation",
value = 10,
min = 1,
max = 400,
step = 1),
#2. Power
sliderInput(inputId = "power",
label = "Power of Study",
min = 0.5,
max = 0.99,
value = 0.8,
step = 0.01),
h6("Power as a decimal not percentage."),
h6("(0.8 means 80% power)"),
#3. Alpha (Significance)
sliderInput(inputId = "alpha",
label = "Significance of Study",
min = 0.01,
max = 0.2,
value = 0.05,
step = 0.01),
h6("Significance of study is most traditionally 0.05 (5%)"),
#4. Meandiff (Difference Between Groups)
numericInput(inputId = "meandiff",
label = "Expected Difference Between Group Means",
value = 20),
#5. Alternative Test
selectInput(inputId = "alt",
label = strong("Alternative Test Options"),
choices = c("Two-Sided" = "two.sided",
"Upper" = "greater",
"Lower" = "less"),
selected = "Two-Sided"),
h6("If unsure, leave at 'Two-Sided'.")
),
#Display only if Power is selected, ask for necessary parameters
conditionalPanel(
condition = "input.type == 'Power'",
#1. Standard Deviation
numericInput(inputId = "stddev2",
label = "Standard Deviation",
value = 10,
min = 1,
max = 400,
step = 1),
#2. Size Per Group
numericInput(inputId = "npergroup",
label = "Number per Group",
value = 120),
h6("Assuming equal number in each group, enter number for ONE group."),
#3. Alpha (Significance)
sliderInput(inputId = "alpha2",
label = "Significance of Study",
min = 0.01,
max = 0.2,
value = 0.05,
step = 0.01),
h6("Significance of study is most traditionally 0.05 (5%)"),
#4. Meandiff (Difference Between Groups)
numericInput(inputId = "meandiff2",
label = "Expected Difference Between Group Means",
value = 20),
#5. Alternative Test
selectInput(inputId = "alt2",
label = strong("Alternative Test Options"),
choices = c("Two-Sided" = "two.sided",
"Upper" = "greater",
"Lower" = "less"),
selected = "Two-Sided"),
h6("If unsure, leave at 'Two-Sided'.")
)
),
#Output:
mainPanel(
textOutput(outputId = "intro"),
textOutput(outputId = "desc"),
conditionalPanel(
condition = "input.type == 'Sample Size'",
textOutput(outputId = "samplesize")
),
conditionalPanel(
condition = "input.type == 'Power'",
textOutput(outputId = "power")
)
)
)
)
server <- function(input, output) {
#Introductory Text
output$intro <- renderText({
"Select an option and adjust the sliders and parameters."
})
#Description of what has been chosen
output$desc <- renderText({
paste("You chose: ", input$type)
})
#If Sample Size is selected, what is the sample size
output$samplesize <- renderText({
paste("Sample Size Per Group for Two-Sample t-test for Mean Diff
Assuming Two Groups and Equal Variances: ",
as.character(ceiling(pwr.t.test(d = input$meandiff / input$stddev,
sig.level = input$alpha,
power = input$power,
type = "two.sample",
alternative = input$alt)$n)))
})
#If Power is selected, what is the power
output$power <- renderText({
paste("Power for Two-Sample t-test for Mean Diff Assuming Two Groups and
Equal Variances: ",
format(round(pwr.t.test(d = input$meandiff2 / input$stddev2,
sig.level = input$alpha2,
n = input$npergroup,
type = "two.sample",
alternative = input$alt2)$power * 100, 2),
nsmall = 2))
})
}
shinyApp(ui = ui, server = server)
EDIT: I have simplified the application and make it all the code reproducible.
EDIT 2: I just discovered that when I use the navBarPage I must click on Additional Parameters -> Colour. Then is coloured as expected.
I'm developing a shiny app which filters my genes and then plots a heatmap of the remaining genes. Recently, I have found shinyHeatmaply package. I have download their global, UI and Server, and when I try it on my own computer they work as expected. Unfortunately, when I try to combine my filter app and their heatmap using navbarPage, the last one is not rending properly.
I have created a minimalist example adding the shinyheatmap to the second tabPanel of navbarPage in the https://shiny.rstudio.com/gallery/shiny-theme-selector.html app, but I get the same grey render anyway.
Same mistake in a simpler application
The UI:
Navbar 1 belongs to the shinytheme application, whilst the content of Navbar 2 belongs to the shinyheatmaply
tagList(
shinythemes::themeSelector(),
navbarPage(
# theme = "cerulean", # <--- To use a theme, uncomment this
"shinythemes",
tabPanel("Navbar 1",
sidebarPanel(
fileInput("file", "File input:"),
textInput("txt", "Text input:", "general"),
sliderInput("slider", "Slider input:", 1, 100, 30),
tags$h5("Deafult actionButton:"),
actionButton("action", "Search"),
tags$h5("actionButton with CSS class:"),
actionButton("action2", "Action button", class = "btn-primary")
),
mainPanel(
tabsetPanel(
tabPanel("Tab 1",
h4("Table"),
tableOutput("table"),
h4("Verbatim text output"),
verbatimTextOutput("txtout"),
h1("Header 1"),
h2("Header 2"),
h3("Header 3"),
h4("Header 4"),
h5("Header 5")
),
tabPanel("Tab 2", "This panel is intentionally left blank"),
tabPanel("Tab 3", "This panel is intentionally left blank")
)
)
),
tabPanel("Navbar 2",
fluidPage(
sidebarLayout(
sidebarPanel(width=4,
h4('Data Selection'),
fileInput(inputId="mydata", label = "Import Data",multiple = T),
uiOutput('data'),
checkboxInput('showSample','Subset Data'),
conditionalPanel('input.showSample',uiOutput('sample')),
hr(),h4('Data Preprocessing'),
column(width=4,selectizeInput('transpose','Transpose',choices = c('No'=FALSE,'Yes'=TRUE),selected = FALSE)),
column(width=4,selectizeInput("transform_fun", "Transform", c(Identity=".",Sqrt='sqrt',log='log',Scale='scale',Normalize='normalize',Percentize='percentize',"Missing values"='is.na10', Correlation='cor'),selected = '.')),
uiOutput('annoVars'),
br(),hr(),h4('Row dendrogram'),
column(width=6,selectizeInput("distFun_row", "Distance method", c(Euclidean="euclidean",Maximum='maximum',Manhattan='manhattan',Canberra='canberra',Binary='binary',Minkowski='minkowski'),selected = 'euclidean')),
column(width=6,selectizeInput("hclustFun_row", "Clustering linkage", c(Complete= "complete",Single= "single",Average= "average",Mcquitty= "mcquitty",Median= "median",Centroid= "centroid",Ward.D= "ward.D",Ward.D2= "ward.D2"),selected = 'complete')),
column(width=12,sliderInput("r", "Number of Clusters", min = 1, max = 15, value = 2)),
#column(width=4,numericInput("r", "Number of Clusters", min = 1, max = 20, value = 2, step = 1)),
br(),hr(),h4('Column dendrogram'),
column(width=6,selectizeInput("distFun_col", "Distance method", c(Euclidean="euclidean",Maximum='maximum',Manhattan='manhattan',Canberra='canberra',Binary='binary',Minkowski='minkowski'),selected = 'euclidean')),
column(width=6,selectizeInput("hclustFun_col", "Clustering linkage", c(Complete= "complete",Single= "single",Average= "average",Mcquitty= "mcquitty",Median= "median",Centroid= "centroid",Ward.D= "ward.D",Ward.D2= "ward.D2"),selected = 'complete')),
column(width=12,sliderInput("c", "Number of Clusters", min = 1, max = 15, value = 2)),
#column(width=4,numericInput("c", "Number of Clusters", min = 1, max = 20, value = 2, step = 1)),
br(),hr(), h4('Additional Parameters'),
column(3,checkboxInput('showColor','Color')),
column(3,checkboxInput('showMargin','Layout')),
column(3,checkboxInput('showDendo','Dendrogram')),
hr(),
conditionalPanel('input.showColor==1',
hr(),
h4('Color Manipulation'),
uiOutput('colUI'),
sliderInput("ncol", "Set Number of Colors", min = 1, max = 256, value = 256),
checkboxInput('colRngAuto','Auto Color Range',value = T),
conditionalPanel('!input.colRngAuto',uiOutput('colRng'))
),
conditionalPanel('input.showDendo==1',
hr(),
h4('Dendrogram Manipulation'),
selectInput('dendrogram','Dendrogram Type',choices = c("both", "row", "column", "none"),selected = 'both'),
selectizeInput("seriation", "Seriation", c(OLO="OLO",GW="GW",Mean="mean",None="none"),selected = 'OLO'),
sliderInput('branches_lwd','Dendrogram Branch Width',value = 0.6,min=0,max=5,step = 0.1)
),
conditionalPanel('input.showMargin==1',
hr(),
h4('Widget Layout'),
column(4,textInput('main','Title','')),
column(4,textInput('xlab','X Title','')),
column(4,textInput('ylab','Y Title','')),
sliderInput('row_text_angle','Row Text Angle',value = 0,min=0,max=180),
sliderInput('column_text_angle','Column Text Angle',value = 45,min=0,max=180),
sliderInput("l", "Set Margin Width", min = 0, max = 200, value = 130),
sliderInput("b", "Set Margin Height", min = 0, max = 200, value = 40)
)
),
mainPanel(
tabsetPanel(
tabPanel("Heatmaply",
tags$a(id = 'downloadData', class = paste("btn btn-default shiny-download-link",'mybutton'), href = "", target = "_blank", download = NA, icon("clone"), 'Download Heatmap as HTML'),
tags$head(tags$style(".mybutton{color:white;background-color:blue;} .skin-black .sidebar .mybutton{color: green;}") ),
plotlyOutput("heatout",height='600px')
),
tabPanel("Data",
DT::dataTableOutput('tables')
)
)
)
)
)
),
tabPanel("Navbar 3", "This panel is intentionally left blank")
)
)
The server:
Regarding to the server, first two output correspond to the shinytheme and the others belong to shinyheatmaply
d=data(package='datasets')$results[,'Item']
d=d[!grepl('[\\()]',d)]
d=d[!d%in%c('UScitiesD','eurodist','sleep','warpbreaks')]
d=d[unlist(lapply(d,function(d.in) eval(parse(text=paste0('ncol(as.data.frame(datasets::',d.in,'))')))))>1]
d=d[-which(d=='mtcars')]
d=c('mtcars',d)
server <- shinyServer(function(input, output,session) {
####This to output belongs to the shinytheme application####
output$txtout <- renderText({
paste(input$txt, input$slider, format(input$date), sep = ", ")
})
output$table <- renderTable({
head(cars, 4)
})
#######################################################
#Up to here the code belongs to shinyheatmaply
output$txtout <- renderText({
paste(input$txt, input$slider, format(input$date), sep = ", ")
})
output$table <- renderTable({
head(cars, 4)
})
TEMPLIST<-new.env()
TEMPLIST$d<-d
#Annotation Variable UI ----
observeEvent(data.sel(),{
output$annoVars<-renderUI({
data.in=data.sel()
NM=NULL
if(any(sapply(data.in,class)=='factor')){
NM=names(data.in)[which(sapply(data.in,class)=='factor')]
}
column(width=4,
selectizeInput('annoVar','Annotation',choices = names(data.in),selected=NM,multiple=T,options = list(placeholder = 'select columns',plugins = list("remove_button")))
)
})
#Sampling UI ----
output$sample<-renderUI({
list(
column(4,textInput(inputId = 'setSeed',label = 'Seed',value = sample(1:10000,1))),
column(4,numericInput(inputId = 'selRows',label = 'Number of Rows',min=1,max=pmin(500,nrow(data.sel())),value = pmin(500,nrow(data.sel())))),
column(4,selectizeInput('selCols','Columns Subset',choices = names(data.sel()),multiple=T))
)
})
})
#Data Selection UI ----
output$data=renderUI({
if(!is.null(input$mydata)) TEMPLIST$d=c(input$mydata$name,TEMPLIST$d)
selData=head(TEMPLIST$d,1)
selectInput("data","Select Data",TEMPLIST$d,selected = selData)
})
#Color Pallete UI ----
output$colUI<-renderUI({
colSel='Vidiris'
if(input$transform_fun=='cor') colSel='RdBu'
if(input$transform_fun=='is.na10') colSel='grey.colors'
selectizeInput(inputId ="pal", label ="Select Color Palette",
choices = c('Vidiris (Sequential)'="viridis",
'Magma (Sequential)'="magma",
'Plasma (Sequential)'="plasma",
'Inferno (Sequential)'="inferno",
'Magma (Sequential)'="magma",
'Magma (Sequential)'="magma",
'RdBu (Diverging)'="RdBu",
'RdYlBu (Diverging)'="RdYlBu",
'RdYlGn (Diverging)'="RdYlGn",
'BrBG (Diverging)'="BrBG",
'Spectral (Diverging)'="Spectral",
'BuGn (Sequential)'='BuGn',
'PuBuGn (Sequential)'='PuBuGn',
'YlOrRd (Sequential)'='YlOrRd',
'Heat (Sequential)'='heat.colors',
'Grey (Sequential)'='grey.colors'),
selected=colSel)
})
#Manual Color Range UI ----
output$colRng=renderUI({
if(!is.null(data.sel())) {
rng=range(data.sel(),na.rm = TRUE)
}else{
rng=range(mtcars) # TODO: this should probably be changed
}
# sliderInput("colorRng", "Set Color Range", min = round(rng[1],1), max = round(rng[2],1), step = .1, value = rng)
n_data = nrow(data.sel())
min_min_range = ifelse(input$transform_fun=='cor',-1,-Inf)
min_max_range = ifelse(input$transform_fun=='cor',1,rng[1])
min_value = ifelse(input$transform_fun=='cor',-1,rng[1])
max_min_range = ifelse(input$transform_fun=='cor',-1,rng[2])
max_max_range = ifelse(input$transform_fun=='cor',1,Inf)
max_value = ifelse(input$transform_fun=='cor',1,rng[2])
a_good_step = 0.1 # (max_range-min_range) / n_data
list(
numericInput("colorRng_min", "Set Color Range (min)", value = min_value, min = min_min_range, max = min_max_range, step = a_good_step),
numericInput("colorRng_max", "Set Color Range (max)", value = max_value, min = max_min_range, max = max_max_range, step = a_good_step)
)
})
#Import/Select Data ----
data.sel=eventReactive(input$data,{
if(input$data%in%d){
eval(parse(text=paste0('data.in=as.data.frame(datasets::',input$data,')')))
}else{
data.in=importSwitch(input$mydata[input$mydata$name%in%input$data,])
}
data.in=as.data.frame(data.in)
# data.in=data.in[,sapply(data.in,function(x) class(x))%in%c('numeric','integer')] # no need for this
return(data.in)
})
#Building heatmaply ----
interactiveHeatmap<- reactive({
data.in=data.sel()
if(input$showSample){
if(!is.null(input$selRows)){
set.seed(input$setSeed)
if((input$selRows >= 2) & (input$selRows < nrow(data.in))){
# if input$selRows == nrow(data.in) then we should not do anything (this save refreshing when clicking the subset button)
if(length(input$selCols)<=1) data.in=data.in[sample(1:nrow(data.in),pmin(500,input$selRows)),]
if(length(input$selCols)>1) data.in=data.in[sample(1:nrow(data.in),pmin(500,input$selRows)),input$selCols]
}
}
}
# ss_num = sapply(data.in,function(x) class(x)) %in% c('numeric','integer') # in order to only transform the numeric values
if(length(input$annoVar)>0){
if(all(input$annoVar%in%names(data.in)))
data.in <- data.in%>%mutate_at(funs(factor),.vars=vars(input$annoVar))
}
ss_num = sapply(data.in, is.numeric) # in order to only transform the numeric values
if(input$transpose) data.in=t(data.in)
if(input$transform_fun!='.'){
if(input$transform_fun=='is.na10'){
updateCheckboxInput(session = session,inputId = 'showColor',value = T)
data.in[, ss_num]=is.na10(data.in[, ss_num])
}
if(input$transform_fun=='cor'){
updateCheckboxInput(session = session,inputId = 'showColor',value = T)
updateCheckboxInput(session = session,inputId = 'colRngAuto',value = F)
data.in=cor(data.in[, ss_num],use = "pairwise.complete.obs")
}
if(input$transform_fun=='log') data.in[, ss_num]= apply(data.in[, ss_num],2,log)
if(input$transform_fun=='sqrt') data.in[, ss_num]= apply(data.in[, ss_num],2,sqrt)
if(input$transform_fun=='normalize') data.in=heatmaply::normalize(data.in)
if(input$transform_fun=='scale') data.in[, ss_num] = scale(data.in[, ss_num])
if(input$transform_fun=='percentize') data.in=heatmaply::percentize(data.in)
}
if(!is.null(input$tables_true_search_columns))
data.in=data.in[activeRows(input$tables_true_search_columns,data.in),]
if(input$colRngAuto){
ColLimits=NULL
}else{
ColLimits=c(input$colorRng_min, input$colorRng_max)
}
distfun_row = function(x) dist(x, method = input$distFun_row)
distfun_col = function(x) dist(x, method = input$distFun_col)
hclustfun_row = function(x) hclust(x, method = input$hclustFun_row)
hclustfun_col = function(x) hclust(x, method = input$hclustFun_col)
p <- heatmaply(data.in,
main = input$main,xlab = input$xlab,ylab = input$ylab,
row_text_angle = input$row_text_angle,
column_text_angle = input$column_text_angle,
dendrogram = input$dendrogram,
branches_lwd = input$branches_lwd,
seriate = input$seriation,
colors=eval(parse(text=paste0(input$pal,'(',input$ncol,')'))),
distfun_row = distfun_row,
hclustfun_row = hclustfun_row,
distfun_col = distfun_col,
hclustfun_col = hclustfun_col,
k_col = input$c,
k_row = input$r,
limits = ColLimits) %>%
layout(margin = list(l = input$l, b = input$b, r='0px'))
p$elementId <- NULL
p
})
#Render Plot ----
observeEvent(input$data,{
output$heatout <- renderPlotly({
if(!is.null(input$data))
interactiveHeatmap()
})
})
#Render Data Table ----
output$tables=DT::renderDataTable(data.sel(),server = T,filter='top',
extensions = c('Scroller','FixedHeader','FixedColumns','Buttons','ColReorder'),
options = list(
dom = 't',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print','colvis'),
colReorder = TRUE,
scrollX = TRUE,
fixedColumns = TRUE,
fixedHeader = TRUE,
deferRender = TRUE,
scrollY = 500,
scroller = TRUE
))
#Clone Heatmap ----
observeEvent({interactiveHeatmap()},{
h<-interactiveHeatmap()
l<-list(main = input$main,xlab = input$xlab,ylab = input$ylab,
row_text_angle = input$row_text_angle,
column_text_angle = input$column_text_angle,
dendrogram = input$dendrogram,
branches_lwd = input$branches_lwd,
seriate = input$seriation,
colors=paste0(input$pal,'(',input$ncol,')'),
distfun_row = input$distFun_row,
hclustfun_row = input$hclustFun_row,
distfun_col = input$distFun_col,
hclustfun_col = input$hclustFun_col,
k_col = input$c,
k_row = input$r,
limits = paste(c(input$colorRng_min, input$colorRng_max),collapse=',')
)
#l=l[!l=='']
l=data.frame(Parameter=names(l),Value=do.call('rbind',l),row.names = NULL,stringsAsFactors = F)
l[which(l$Value==''),2]='NULL'
paramTbl=print(xtable::xtable(l),type = 'html',include.rownames=FALSE,print.results = F,html.table.attributes = c('border=0'))
h$width='100%'
h$height='800px'
s<-tags$div(style="position: relative; bottom: 5px;",
HTML(paramTbl),
tags$em('This heatmap visualization was created using',
tags$a(href="https://github.com/yonicd/shinyHeatmaply/",target="_blank",'shinyHeatmaply'),
Sys.time()
)
)
output$downloadData <- downloadHandler(
filename = function() {
paste("heatmaply-", gsub(' ','_',Sys.time()), ".html", sep="")
},
content = function(file) {
libdir <- paste(tools::file_path_sans_ext(basename(file)),"_files", sep = "")
htmltools::save_html(htmltools::browsable(htmltools::tagList(h,s)),file=file,libdir = libdir)
if (!htmlwidgets:::pandoc_available()) {
stop("Saving a widget with selfcontained = TRUE requires pandoc. For details see:\n",
"https://github.com/rstudio/rmarkdown/blob/master/PANDOC.md")
}
htmlwidgets:::pandoc_self_contained_html(file, file)
unlink(libdir, recursive = TRUE)
}
)
})
#End of Code ----
})
Thanks in advance to the hero who solves this problem.
Best rewards, Daniel.
The problem was a conflict between a conditional panel (which uses js) and the navbar page, for any reason default parameters were not read, thus autocoloring which should be enabled wasn't. I just removed this conditional panel and set always its options.