This question already has answers here:
R shiny sliderInput with restricted range
(2 answers)
Closed 5 years ago.
I have a sliderInput() ranging from 0 to 100 and would like to limit it to only allow values from 0 to 10. Is there a way to achieve that?
Note: This may seem like a silly request (just set max = 10 to shorten the scale) but it's for good reason I would like to maintain the full scale.
You can do something link this:
rm(list = ls())
library(shiny)
ui <-basicPage(
sliderInput("slider1", "Slider 1: ", min = 0, max = 100, value = 0, step=1)
)
server <- function(input, output,session) {
observeEvent(input$slider1,{
if(input$slider1 > 10){
updateSliderInput(session, "slider1", min = 0,max=100, value = 10)
}
})
}
runApp(list(ui = ui, server = server))
Related
I'm using tbl_regression from the gtsummary package to show the results of cox proportional hazards models. Due to circumstances regarding sensitive personal information, I am not allowed to show strata with a number of observations less than 5. I can, however, still show the estimates, CIs etc. for those strata, but not how many persons have had the event if the number is less than 5. In these number of events strata with less than 5 observations, I would like to insert just a line to indicate this.
From what I have read, the modify_table_body function is perhaps the correct function to achieve this. However, I cannot manage to find out how to use it correctly. Is there any way to define that the regression table should not show N_event less than 5 but still show HRs, CIs, person years ect. for those given stratas?
Below is my preliminary code in which I thought maybe should be followed by "%>% modify_table_body()".
Thank you in advance for your help!
Best,
Mathilde
cox_cat_cns2 <- coxph(Surv(TTD_year, Dod_status) ~ Highest_Edu_Household + Diag_year + Age_household_mom_num + Age_household_dad_num + Country_origin_household, data = data_cox_cat_cns)
cox_cat_cns_adj_table <- tbl_regression(cox_cat_cns2,
label = c(Highest_Edu_Household ~ "Highest parental education",
Diag_year ~ "Year of diagnosis",
Age_household_mom_num ~ "Mother's age at diagnosis",
Age_household_dad_num ~ "Father's age at diagnosis",
Country_origin_household ~ "Parents' country of origin"),
exponentiate = TRUE) %>%
add_nevent(location = "level") %>%
bold_labels() %>%
italicize_levels() %>%
modify_table_styling(
columns = estimate,
rows = reference_row %in% TRUE,
missing_symbol = "Ref.") %>%
modify_footnote(everything() ~ NA, abbreviation = TRUE) %>%
modify_table_styling(
column = p.value,
hide = TRUE) %>%
modify_header(
label = "",
stat_nevent = "**Events (N)**",
exposure ~ "**Person years**")
You can 1. define a new function to "style" the number of events that collapses any counts less than 5 as "<5", then 2. use that function to style the column in the resulting table. Example below!
library(gtsummary)
#> #Uighur
library(survival)
library(dplyr)
style_number5 <- function(x, ...) {
ifelse(
x < 5,
paste0("<", style_number(5, ...)),
style_number(x, ...)
)
}
style_number5(4:6)
#> [1] "<5" "5" "6"
tbl <-
trial %>%
slice(1:45) %>%
coxph(Surv(ttdeath, death) ~ stage, data = .) %>%
tbl_regression(exponentiate = TRUE) %>%
add_nevent(location = "level") %>%
modify_fmt_fun(stat_nevent ~ style_number5)
Created on 2022-04-21 by the reprex package (v2.0.1)
I have two input variables, and changing one will cause the change of the other one.
Further to that, if the value of input is outside limits it should default to min (if below) or max (if above) value.
All works fine as long as up and down arrows are being used.
The moment I am typing value 1 in Input1 it goes crazy.
Same if I am deleting Input2, even before I am typing anything...
I am aware that it must have something to do with reactive values, but can not fix it...
Any suggestion will be very much appreciated!
library(shiny)
ui <- fluidPage(
fluidRow(
uiOutput("Input1"),
numericInput("Input2", "Input 2",
min = 50, max = 150,
value = 100, step = 1)),
tableOutput("result")
)
#########################################################
server <- function(input, output, session) {
global <- reactiveValues(numVal = 10, numMin = 5, numMax = 15)
numVal <- reactive({
if(!is.null(input$Input1)){
if(input$Input1 < global$numMin) return(global$numMin)
if(input$Input1 > global$numMax) return(global$numMax)
return(input$Input1)
}else{
return(global$numVal)
}
})
output$Input1 <- renderUI(numericInput("Input1", "Input 1",
min = global$numMin, max = global$numMax,
value = numVal(), step = 0.1))
# when Input1 change, update Input2
observeEvent(input$Input1, {
updateNumericInput(session = session,
"Input2",
value = format(round(input$Input1*10, 0), nsmall = 0))
})
# when Input2 change, update Input1
observeEvent(input$Input2, {
updateNumericInput(session = session,
"Input1",
value = format(round(input$Input2*0.1, 1), nsmall = 1))
})
inputdata <- reactive({
data <- data.frame(Coef = as.numeric(input$Input1))
data
})
output$result <- renderTable({
data = inputdata()
resultTable = as.character(round((data$Coef + 10)*100, digits=2))
resultTable
})
}
#########################################################
shinyApp(ui, server)
You are on the brink of getting into a race condition:
Input 1 changes Input 2 changes Input 1 changes Input 2...
So foremost you should reconsider your design. You can use debounce / throttle to avoid some of the race consition by telling Shiny not too fire too quickly and as the updates are bijective you may achieve what you want, but I would really think about your design b/c these circle dependencies are almost never a good idea.
Having said that here is a solution which behaves better (N.B. I removed the dynamic rendering of the second input element as it has nothing to do wiht the problem at hand). It is not perfect, b/c you will eventually end up in a racing condition, but you can soften this situation by playing w/ the debouncing factors.
library(shiny)
ui <- fluidPage(
fluidRow(
numericInput("Input1", "Input 1",
min = 5, max = 15, value = 10, step = .1),
numericInput("Input2", "Input 2",
min = 50, max = 150,
value = 100, step = 1)),
tableOutput("result")
)
server <- function(input, output, session) {
## debounce both input, i.e. they are firing onyl if no change within 1sec happens
## c.f. ?debounce
getI1 <- reactive(input$Input1) %>%
debounce(1000)
getI2 <- reactive(input$Input2) %>%
debounce(1000)
observeEvent(input$Input1, {
updateNumericInput(session = session,
"Input2",
value = format(round(getI1() * 10, 0), nsmall = 0))
})
observeEvent(input$Input2, {
updateNumericInput(session = session,
"Input1",
value = format(round(getI2() * 0.1, 1), nsmall = 1))
})
inputdata <- reactive({
data <- data.frame(Coef = as.numeric(input$Input1))
data
})
output$result <- renderTable({
data = inputdata()
resultTable = as.character(round((data$Coef + 10)*100, digits=2))
resultTable
})
}
shinyApp(ui, server)
I am using dygraphs for R and I opened the following issue on GitHub the other day, however, I have not yet received an answer. Therefore, I am hoping someone in here will be able to answer my question.
I want to know if it is possible to show all the values of the prediction interval in the legend, i.e. , lower, actual, upper, without having them as three separate plain dySeries? I like the look of the shading that the upper/lower bars bring, but I would also like to be able to hover over a point and see all the values for that particular point, not just the middle one. If such a function does not exists, is there an easy workaround, maybe with fillGraph = TRUE or something?
library(dygraphs)
hw <- HoltWinters(ldeaths)
p <- predict(hw, n.ahead = 72, prediction.interval = TRUE)
dygraph(p, main = "Predicted Lung Deaths (UK)") %>%
dySeries(c("lwr", "fit", "upr"), label = "Deaths")
The preceding code is the example from the web page, which is similar to my problem. I simply want to see the lwr and upr values in the legend when hovering.
So I found a workaround for anybody looking for something similar.
library(dygraphs)
hw <- HoltWinters(ldeaths)
p <- predict(hw, n.ahead = 72, prediction.interval = TRUE)
max <- p[,2]
min <- p[,3]
p <- ts.union(p, max, min)
dygraph(p, main = "Predicted Lung Deaths (UK)") %>%
dySeries(c("p.lwr", "p.fit", "p.upr"), label = "Deaths") %>%
dySeries("max", label = "Max", pointSize = 0.01, strokeWidth = 0.001) %>%
dySeries("min", label = "Max", pointSize = 0.01, strokeWidth = 0.001)
Obviously, this can be modified to suit your needs (e.g. color of the points etc.) The main idea in this method is simply to create two new columns containing the same information that is used in the bands, and then to make the lines to these too small to see.
I have a dataset in which I am graphing means from 4 treatments over time, along with their standard errors, at 2 sites. The standard error bars are not being assigned properly to their respective means --they are going to both panels - can you please advise? See example:
d <- data.frame(site=rep(1:2,each=12),time=rep(1:3,8),trt=rep(rep(1:4,each=3),2))
d$mn <- rnorm(24,4,1)
d$se <- rnorm(24,2,1)
d$ul <- d$mn+d$se # create y value for standard error upper limit
my.panel <- function(x,y, ...){
panel.xyplot(x, y, ...)
panel.arrows(x, y, x, d$ul, length = 0.1,
angle = 90)
}
xyplot(mn ~ time|site,data=d,
group = trt,
type=c('p','l'),
panel = my.panel
)
I am creating a input list for user selection using selectInput(....multiple=TRUE), where user can select multiple options, but I am unable to check/read what options user selects in my server.R.
If anyone has successfully tried it can you please share?
For example -
For a directory which has folowing file -
/User/DE/AvsB.de.txt-
Feature.ID Read.Count.All Read.Count.A Read.Count.B FC
ENSG00000121898 3367.375403 6734.750807 0 0
ENSG00000104435 2161.235573 4322.471145 0 0
ENSG00000229847 2111.660196 4223.320392 0 0
ENSG00000046889 1302.993351 2605.986702 0 0
/User/DE/CvsD.de.txt -
Feature.ID Read.Count.All Read.Count.C Read.Count.D FC
ENSG00000248329 373.0309339 746.0618679 0 0
ENSG00000144115 352.3786793 704.7573586 0 0
ENSG00000158528 351.6252529 703.2505057 0 0
ENSG00000189058 350.5375828 701.0751656 0 0
library(gtools)
D_files <- list.files(path = "/User/DE/",pattern = "*.de.txt" ,recursive = F, full.names = T)
D_filename <- vector()
for(i in 1:length(D_files)){
D_filename[i] <- D_files[i]
}
D_filename <- unlist(strapplyc(D_filename, "/User/DE/(.*).de.txt"))
names(D_files)<- D_filename
ui <- fluidPage(
mainPanel(
uiOutput("Quad_plot_comparison"),
HTML("<br><br>"),
br()
)
)
server <- function(input, output) {
output$Quad_plot_comparison <- renderUI({
selectInput(inputId = "vars",label = h3("Select comparison"), choices = mixedsort(D_files), multiple = T)
})
}
shinyApp(ui, server)
My code shows the file names in the input box, but I need to do following
1- Select multiple file names from the box
2- Read user input ( variables in the input box)
3- Read the files corresponding to these user input into a data frame
I am not even able to get the second step to work, any help will work!
Thanks!
This is a small example on how to use multiple selection in selectInput. You can adapt it to you scenario by reading the file in the reactive:
library(shiny)
shinyApp(ui=fluidPage(selectInput("select", "choose", c(1,2,3), multiple = TRUE),
textOutput("selected", inline=TRUE)),
server=function(input, output){
selected <- reactive(ifelse(is.null(input$select), "nothing",
paste(input$select, collapse=",")))
output$selected <- renderText(paste("Selected=",selected()))
})