valuebox missing true/false statement - if-statement

I am attempting to have two if else statements in a renderValuebox in shiny R. Here's the code:
observe({
a <- which(blkname==input$e0)
start <- input$dateRange[1]
end <- input$dateRange[2]
confInt <- input$CI
inc <- input$increment
output$Name <- renderText(paste0("Overview of ",input$e0," block"))
start1 <- as.character(format(input$dateRange[1], format="%B %d %Y"))
end1 <- as.character(format(input$dateRange[2], format="%B %d %Y"))
output$Head <- renderText(paste0("Distribution of dry matter across ", input$e0, " between ",start1, " and ", end1))
pts$DryMatter <- pts$DryMatter+(pts$Amend*inc)
pts$DryMatter <- round(pts$DryMatter, digits=2)
grap <- pts[which(pts$Date>start&pts$Date<end),]
grap <- grap[which(grap$paddock==a),]
grap$DryMatter<- round(grap$DryMatter, digits=2)
yup <- round(mean(grap$DryMatter), digits=2)
nump <- nrow(grap)
grapdevdm <- grap[which(grap$Amend==min(grap$Amend)),]
grapdev <- sd(grapdevdm$DryMatter)
grapsampnum <- nrow(grapdevdm)
grapdevmean <- mean(grapdevdm$DryMatter)
cv <- (grapdev/grapdevmean)*100
sampReq <-(1.7*1.7)*(cv*cv)/((100-confInt)^2)
~
output$treenum <- renderValueBox({
valueBox(
paste0(nrow(grap), "Trees sampled out of ", sampReq, "required."),
if(nrow(grap)>=sampReq){
icon = icon("thumbs-up", lib = "glyphicon")}else
{icon = icon("thumbs-down", lib = "glyphicon")},
if(nrow(grap)>=sampReq){ color = "green"} else {colour = "red"}
)
})
I am receiving Warning: Error in if: missing value where TRUE/FALSE needed
However both if else is completed, maybe I am missing something.
Cheers,

Related

shiny DT::renderDT() multiple tables

I can't get renderDT() to display multiple data tables that my script creates. The code below. Reading the input table works, the progress indicator progresses through each line, but the hg38 and hg19 tabs are empty in the display.
If I move the hg38 renderDT() inside of the my_data <- reactive( it will display the hg38 table, but I get the following error and nothing in the hg19 tab
```Warning: Error in $: object of type 'closure' is not subsettable```
```105: <Anonymous>```
If I move both renderDT() inside the my_data <- reactive( I get nothing in either tab. I'm clearly misunderstanding something, but I'm not sure what.
library(shiny)
library(DT)
library("dplyr")
library(GenomeInfoDb)
library(BSgenome)
library("MafDb.gnomAD.r2.1.hs37d5")
library("MafH5.gnomAD.v3.1.2.GRCh38")
library(BSgenome.Hsapiens.UCSC.hg19)
library(BSgenome.Hsapiens.UCSC.hg38)
mafdb_hg19 <- MafDb.gnomAD.r2.1.hs37d5
mafdb_hg38 <- MafH5.gnomAD.v3.1.2.GRCh38
hg19 <- BSgenome.Hsapiens.UCSC.hg19
hg38 <- BSgenome.Hsapiens.UCSC.hg38
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File", accept = ".csv"),
#checkboxInput("header", "Header", TRUE),
width = 2
),
mainPanel(
tabsetPanel(
tabPanel("Primers(input)", DT::dataTableOutput("primers")),
tabPanel("SNPs(hg38)", DT::dataTableOutput("hg38")),
tabPanel("SNPs(hg19)", DT::dataTableOutput("hg19"))
)
)
)
)
server <- function(input, output){
primer_file <- reactive(
{
file <- input$file1
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "csv", "Please upload a csv file"))
primer_file <- as.data.frame(read.csv(file$datapath, header = TRUE))
return(primer_file)
})
output$primers <- DT::renderDT(primer_file())
my_data <- reactive(
{
primers_hg38 <- data.frame(primer_id=character(),
seq=character(),
chr=character(),
hg38_pos=integer(),
AF_allpopmax_hg38=integer(),
stringsAsFactors=FALSE)
primers_hg19 <- data.frame(primer_id=character(),
seq=character(),
chr=character(),
hg19_pos=integer(),
AF_afr=integer(),AF_amr=integer(), AF_asj=integer(), AF_eas=integer(), AF_fin=integer(), AF_nfe=integer(), AF_oth=integer(),
stringsAsFactors=FALSE)
progress <- shiny::Progress$new()
# Make sure it closes when we exit this reactive, even if there's an error
on.exit(progress$close())
progress$set(message = "Calculating", value = 0)
lastrow <- nrow(primer_file())
firstrow=1
for (no in (firstrow:lastrow))
{
row = primer_file()[no,]
temp_chr <- row$chr
temp_FP <- row$FP
temp_RP <- row$RP
progress$inc(1/lastrow, detail = paste("line ", no))
###################lets do hg38 first######################
subject_hg38 <- hg38[[temp_chr]]
products_hg38 <- matchProbePair(temp_FP,temp_RP,subject_hg38)
amp_start_hg38 = (start(products_hg38))
fp_end_hg38 = (start(products_hg38) + as.integer(nchar(row$FP)) - 1)
rp_start_hg38 = ( (start(products_hg38) + width(products_hg38)) - as.integer(nchar(row$RP)) )
amp_end_hg38 = (start(products_hg38) + width(products_hg38) - 1)
fp_range_hg38 <- GRanges(seqnames=temp_chr, IRanges(start=amp_start_hg38:fp_end_hg38, width=1))
fp_scores_hg38 <- gscores(mafdb_hg38,fp_range_hg38,pop="AF_allpopmax")
fp_scores_hg38 <- as.data.frame(fp_scores_hg38)
rp_range_hg38 <- GRanges(seqnames=temp_chr, IRanges(start=rp_start_hg38:amp_end_hg38, width=1))
rp_scores_hg38 <- gscores(mafdb_hg38,rp_range_hg38,pop="AF_allpopmax")
rp_scores_hg38 <- as.data.frame(rp_scores_hg38)
#primers_hg38 <- data.frame(primer_id=character(),
# seq=character(),
# chr=character(),
# hg38_pos=integer(),
# AF_allpopmax_hg38=integer(),
# stringsAsFactors=FALSE)
primers_hg38 <- bind_rows(primers_hg38,setNames(data.frame(primer_id <- paste0(row$ID,"_F"),
seq <- temp_FP,
chr <- fp_scores_hg38$seqnames,
hg38_pos <- fp_scores_hg38$start,
AF_allpopmax_hg38 <- fp_scores_hg38$AF_allpopmax, stringsAsFactors=FALSE),c("primer_id", "seq", "chr","hg38_pos","AF_allpopmax_hg38")))
#names(primers_hg38) <- c("primer_id","seq","chr","hg38_pos","AF_allpopmax_hg38")
primers_hg38 <- bind_rows(primers_hg38,setNames(data.frame(primer_id <- paste0(row$ID,"_R"),
seq <- temp_RP,
chr <- rp_scores_hg38$seqnames,
hg38_pos <- rp_scores_hg38$start,
AF_allpopmax_hg38 <- rp_scores_hg38$AF_allpopmax,stringsAsFactors=FALSE),c("primer_id", "seq", "chr","hg38_pos","AF_allpopmax_hg38")))
##########################now hg19######################################
#names(primers_hg38) <- c("primer_id","seq","chr","hg38_pos","AF_allpopmax_hg38")
subject_hg19 <- hg19[[temp_chr]]
products_hg19 <- matchProbePair(temp_FP,temp_RP,subject_hg19)
amp_start_hg19 = start(products_hg19)
fp_end_hg19 = ( start(products_hg19) + as.integer(nchar(row$FP)) - 1)
rp_start_hg19 = ( (start(products_hg19) + width(products_hg19)) - as.integer(nchar(row$RP)) )
amp_end_hg19 = (start(products_hg19) + width(products_hg19) - 1)
fp_range_hg19 <- GRanges(seqnames=temp_chr, IRanges(start=amp_start_hg19:fp_end_hg19, width=1))
fp_scores_hg19 <- gscores(mafdb_hg19,fp_range_hg19,pop=c("AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth"))
fp_scores_hg19 <- as.data.frame(fp_scores_hg19)
rp_range_hg19 <- GRanges(seqnames=temp_chr, IRanges(start=rp_start_hg19:amp_end_hg19, width=1))
rp_scores_hg19 <- gscores(mafdb_hg19,rp_range_hg19,pop=c("AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth"))
rp_scores_hg19 <- as.data.frame(rp_scores_hg19)
primers_hg19 <- bind_rows(primers_hg19,setNames(data.frame(primer_id <- paste0(row$ID,"_F"),
seq <- temp_FP,
chr <- fp_scores_hg19$seqnames,
hg19_pos <- fp_scores_hg19$start,
AF_afr <- fp_scores_hg19$AF_afr,
AF_amr <- fp_scores_hg19$AF_amr,
AF_asj <- fp_scores_hg19$AF_asj,
AF_eas <- fp_scores_hg19$AF_eas,
AF_fin <- fp_scores_hg19$AF_fin,
AF_nfe<- fp_scores_hg19$AF_nfe,
AF_oth<- fp_scores_hg19$AF_oth,
stringsAsFactors=FALSE),
c("primer_id", "seq", "chr","hg19_pos","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth")))
primers_hg19 <- bind_rows(primers_hg19,setNames(data.frame(primer_id <- paste0(row$ID,"_R"),
seq <- temp_RP,
chr <- rp_scores_hg19$seqnames,
hg19_pos <- rp_scores_hg19$start,
AF_afr <- rp_scores_hg19$AF_afr,
AF_amr <- rp_scores_hg19$AF_amr,
AF_asj <- rp_scores_hg19$AF_asj,
AF_eas <- rp_scores_hg19$AF_eas,
AF_fin <- rp_scores_hg19$AF_fin,
AF_nfe<- rp_scores_hg19$AF_nfe,
AF_oth<- rp_scores_hg19$AF_oth,
stringsAsFactors=FALSE),
c("primer_id", "seq", "chr","hg19_pos","AF_afr","AF_amr","AF_asj","AF_eas","AF_fin","AF_nfe","AF_oth")))
}
return(list(as.data.frame(primers_hg38), as.data.frame(primers_hg19)))
})
output$hg38 <- DT::renderDT(my_data()$primers_hg38)
#, options = list(paging = F, info = F, search = list(),
# dom = "Brtip", fixedColumns = T, fixedHeader = T,
# buttons = c("copy", "excel")),
# fillContainer = TRUE)
output$hg19 <- DT::renderDT(my_data()$primers_hg19, options = list(paging = F, info = F, search = list(),
dom = "Brtip", fixedColumns = T, fixedHeader = T,
buttons = c("copy", "excel")),
fillContainer = TRUE)
}
shinyApp(ui, server)
Please consider posting a MRE in the future. If you access the data as my_data()[[1]] it should work. However, if you define a named list, your method works. Take a look at an MRE below.
library(DT)
ui <- fluidPage(
DTOutput("t1"), DTOutput("t2")
)
server <- function(input, output) {
myd <- reactive(list(iris,mtcars))
myd2 <- reactive(list(ab=rock,cd=pressure))
output$t1 <- renderDT(head(myd()[[2]])) ### works
# output$t1 <- renderDT(myd()$mtcars) ### does not work
output$t2 <- renderDT(head(myd2()$ab)) ### works as a named list
}
shinyApp(ui = ui, server = server)

Error : length of 'dimnames' [2] not equal to array extent - but number of columns IS equal to number of columnnames

maybe you can help me with a small problem. I picked some data out of a bigger data file and combined those data in the end to a table. In the last line I want to put columnnames to that table. Before I put those columnnames to that table the length is = 115. But when I put the columnnames to that table the length is suddenly = 112 and the above mentioned error occurs. But I also counted the number of columnnames and there are 115. Maybe do you have clue what to do?
Thank you in advance and kind regards,
Julian
Code:
setwd("/home/julian/Schreibtisch/Test")
# Alle einzulesenden Daten
dirnames <- dir()
for(i in 1:length(dirnames)){
# Basis-Angaben
INSIST_basics_1 <- read.csv(dirnames[i])[ ,c('mouse.x', 'TN.Nr.')]
INSIST_basics_1 <- subset(INSIST_basics_1, mouse.x > 0)
INSIST_basics_1 <- INSIST_basics_1[,c('TN.Nr.')]
INSIST_basics_1 <- c(INSIST_basics_1)
INSIST_basics_1 <- rbind(INSIST_basics_1)
INSIST_basics_2 <- read.csv(dirnames[i])[ ,c('mouse.x', 'Termin')]
INSIST_basics_2 <- subset(INSIST_basics_2, mouse.x > 0)
INSIST_basics_2 <- INSIST_basics_2[,c('Termin')]
INSIST_basics_2 <- c(INSIST_basics_2)
INSIST_basics_2 <- rbind(INSIST_basics_2)
INSIST_basics_3 <- read.csv(dirnames[i])[ ,c('mouse.x', 'Zuweisung')]
INSIST_basics_3 <- subset(INSIST_basics_3, mouse.x > 0)
INSIST_basics_3 <- INSIST_basics_3[,c('Zuweisung')]
INSIST_basics_3 <- c(INSIST_basics_3)
INSIST_basics_3 <- rbind(INSIST_basics_3)
INSIST_basics <- c(INSIST_basics_1,INSIST_basics_2,INSIST_basics_3)
INSIST_basics <- rbind(INSIST_basics)
# VAS
INSIST_VAS <- read.csv(dirnames[i])[ ,c('Word', 'trials_4.thisIndex', 'trials_6.thisIndex', 'trials_10.thisIndex', 'trials_7.thisIndex', 'trials_8.thisIndex', 'slider.response')]
INSIST_VAS <- INSIST_VAS[-which(INSIST_VAS$Word == ""), ]
INSIST_VAS_1 <- subset(INSIST_VAS, trials_4.thisIndex >= 0)
INSIST_VAS_1 <- INSIST_VAS_1[order(INSIST_VAS_1$trials_4.thisIndex),]
INSIST_VAS_1 <- INSIST_VAS_1[,c('slider.response')]
INSIST_VAS_1 <- (INSIST_VAS_1 - 1) *100
INSIST_VAS_2 <- subset(INSIST_VAS, trials_6.thisIndex >= 0)
INSIST_VAS_2 <- INSIST_VAS_2[order(INSIST_VAS_2$trials_6.thisIndex),]
INSIST_VAS_2 <- INSIST_VAS_2[,c('slider.response')]
INSIST_VAS_2 <- (INSIST_VAS_2 - 1) *100
INSIST_VAS_3 <- subset(INSIST_VAS, trials_10.thisIndex >= 0)
INSIST_VAS_3 <- INSIST_VAS_3[order(INSIST_VAS_3$trials_10.thisIndex),]
INSIST_VAS_3 <- INSIST_VAS_3[,c('slider.response')]
INSIST_VAS_3 <- (INSIST_VAS_3 - 1) *100
INSIST_VAS_4 <- subset(INSIST_VAS, trials_7.thisIndex >= 0)
INSIST_VAS_4 <- INSIST_VAS_4[order(INSIST_VAS_4$trials_7.thisIndex),]
INSIST_VAS_4 <- INSIST_VAS_4[,c('slider.response')]
INSIST_VAS_4 <- (INSIST_VAS_4 - 1) *100
INSIST_VAS_5 <- subset(INSIST_VAS, trials_8.thisIndex >= 0)
INSIST_VAS_5 <- INSIST_VAS_5[order(INSIST_VAS_5$trials_8.thisIndex),]
INSIST_VAS_5 <- INSIST_VAS_5[,c('slider.response')]
INSIST_VAS_5 <- (INSIST_VAS_5 - 1) *100
INSIST_VAS_all <- c(INSIST_VAS_1,INSIST_VAS_2,INSIST_VAS_3,INSIST_VAS_4,INSIST_VAS_5)
INSIST_VAS_all <- rbind(INSIST_VAS_all)
# FB tDCS
INSIST_tDCS <- read.csv(dirnames[i])[ ,c('itemIndex','questions', 'ratings')]
INSIST_tDCS <- INSIST_tDCS[-which(INSIST_tDCS$questions == ""), ]
INSIST_tDCS <- INSIST_tDCS[,c('ratings')]
INSIST_tDCS <- c(INSIST_tDCS)
INSIST_tDCS <- rbind(INSIST_tDCS)
# FB Zustand
INSIST_Zustand <- read.csv(dirnames[i])[ ,c('questionText', 'trials_9.thisIndex', 'trials_13.thisIndex', 'trials_15.thisIndex', 'slider_13.response')]
INSIST_Zustand <- INSIST_Zustand[-which(INSIST_Zustand$questionText == ""), ]
INSIST_Zustand_1 <- subset(INSIST_Zustand, trials_9.thisIndex >= 0)
INSIST_Zustand_1 <- INSIST_Zustand_1[order(INSIST_Zustand_1$trials_9.thisIndex),]
INSIST_Zustand_1 <- INSIST_Zustand_1[,c('slider_13.response')]
INSIST_Zustand_1 <- (INSIST_Zustand_1 - 1) *100
INSIST_Zustand_2 <- subset(INSIST_Zustand, trials_13.thisIndex >= 0)
INSIST_Zustand_2 <- INSIST_Zustand_2[order(INSIST_Zustand_2$trials_13.thisIndex),]
INSIST_Zustand_2 <- INSIST_Zustand_2[,c('slider_13.response')]
INSIST_Zustand_2 <- (INSIST_Zustand_2 - 1) *100
INSIST_Zustand_3 <- subset(INSIST_Zustand, trials_15.thisIndex >= 0)
INSIST_Zustand_3 <- INSIST_Zustand_3[order(INSIST_Zustand_3$trials_15.thisIndex),]
INSIST_Zustand_3 <- INSIST_Zustand_3[,c('slider_13.response')]
INSIST_Zustand_3 <- (INSIST_Zustand_3 - 1) *100
INSIST_Zustand_all <- c(INSIST_Zustand_1,INSIST_Zustand_2,INSIST_Zustand_3)
INSIST_Zustand_all <- rbind(INSIST_Zustand_all)
# Szenarien
INSIST_Szenarien <- read.csv(dirnames[i])[ ,c('scenario', 'trials_11.thisIndex', 'rating_2.response')]
INSIST_Szenarien <- INSIST_Szenarien[-which(INSIST_Szenarien$scenario == ""), ]
INSIST_Szenarien <- INSIST_Szenarien[order(INSIST_Szenarien$trials_11.thisIndex),]
INSIST_Szenarien <- INSIST_Szenarien[,c('rating_2.response')]
INSIST_Szenarien <- c(INSIST_Szenarien)
INSIST_Szenarien <- rbind(INSIST_Szenarien)
# Alle Abschnitte zusammenfuehren
INSIST_tab <- c(INSIST_basics, INSIST_VAS_all, INSIST_tDCS, INSIST_Zustand_all, INSIST_Szenarien)
INSIST_tab <- rbind(INSIST_tab)
colnames(INSIST_tab) <- c( "TN_Nr", "Termin", "Zuweisung", "Hungrig_1", "Satt_1", "Durstig_1", "Aengstlich_1", "Froehlich_1", "Gestresst_1", "Schlaefrig_1", "Konzentriert_1", "Traurig_1", "Essen_generell_1", "Essen_suess_1", "Essen_herzhaft_1", "Hungrig_2", "Satt_2", "Durstig_2", "Aengstlich_2", "Froehlich_2", "Gestresst_2", "Schlaefrig_2", "Konzentriert_2", "Traurig_2", "Essen_generell_2", "Essen_suess_2", "Essen_herzhaft_2", "Hungrig_3", "Satt_3", "Durstig_3", "Aengstlich_3", "Froehlich_3", "Gestresst_3", "Schlaefrig_3", "Konzentriert_3", "Traurig_3", "Essen_generell_3", "Essen_suess_3", "Essen_herzhaft_3", "Hungrig_4", "Satt_4", "Durstig_4", "Aengstlich_4", "Froehlich_4", "Gestresst_4", "Schlaefrig_4", "Konzentriert_4", "Traurig_4", "Essen_generell_4", "Essen_suess_4", "Essen_herzhaft_4", "Hungrig_5", "Satt_5", "Durstig_5", "Aengstlich_5", "Froehlich_5", "Gestresst_5", "Schlaefrig_5", "Konzentriert_5", "Traurig_5", "Essen_generell_5", "Essen_suess_5", "Essen_herzhaft_5", "tDCS_Jucken_1", "tDCS_Schmerzen_1", "tDCS_Brennen_1", "tDCS_Waerme_1", "tDCS_Metall_1", "tDCS_Ermuedung_1", "tDCS_Kopf_1", "tDCS_Jucken_2", "tDCS_Schmerzen_2", "tDCS_Brennen_2", "tDCS_Waerme_2", "tDCS_Metall_2", "tDCS_Ermuedung_2", "tDCS_Kopf_2","tDCS_Jucken_3", "tDCS_Schmerzen_3", "tDCS_Brennen_3", "tDCS_Waerme_3", "tDCS_Metall_3", "tDCS_Ermuedung_3", "tDCS_Kopf_3", 'Zustand_Herr_1', 'Zustand_kontrollieren_1', 'Zustand_Versuchungen_1', 'Zustand_Stimmung_1', 'Zustand_Druck_1', 'Zustand_Kontrolle_1', 'Zustand_willensstark_1', 'Zustand_erschrocken_1', 'Zustand_ueberrascht_1', 'Zustand_Herr_2', 'Zustand_kontrollieren_2', 'Zustand_Versuchungen_2', 'Zustand_Stimmung_2', 'Zustand_Druck_2', 'Zustand_Kontrolle_2', 'Zustand_willensstark_2', 'Zustand_erschrocken_2', 'Zustand_ueberrascht_2','Zustand_Herr_3', 'Zustand_kontrollieren_3', 'Zustand_Versuchungen_3', 'Zustand_Stimmung_3', 'Zustand_Druck_3', 'Zustand_Kontrolle_3', 'Zustand_willensstark_3', 'Zustand_erschrocken_3', 'Zustand_ueberrascht_3','Kino', 'Pralinen', 'Zuhause', 'Weihnachtsessen' ) # Spaltennamen
}```

How can I get a table to print under a picture using a loop in a .rmd with word_document?

I am trying to create a .rmd file that takes all of the pictures for a field day and the notes that was taken and create a report. I am able to get the pictures to plot but the no matter what I try the table with the notes does not want to print. Below is the loop I am utilizing:
for(i in 1:nrow(subset_Inventory_data)) {
singlept <- subset_Inventory_data[i,]
picture <- pictureLookup[singlept$GlobalID == pictureLookup$REL_GLOBAL,]
#PRINT PICTURE
plot(image_read(paste(baseURL,picture$UID,sep = "")) %>%
# image_resize("400x400") %>%
image_rotate(degrees = 90)
)
#creating table underneath picture
Categories <- c("Latitude", "Longitude", "Road Width", "Conditon", "Lock Present","Additional Notes")
sum_table <- data.frame(Category = character(),
Information = character(),
stringsAsFactors = FALSE)
sum_table <- rbind(sum_table,Categories,
stringsAsFactors = FALSE)
colnames(sum_table) <- Categories
sum_table$Latitude <- sprintf("%f",singlept$LAT)
sum_table$Longitude <-sprintf("%f",singlept$LONG)
sum_table$`Road Width` <- paste(singlept$Gate_Width,"feet")
sum_table$Conditon <- singlept$Condition
sum_table$`Lock Present` <- singlept$GlobalID
sum_table$`Additional Notes` <- singlept$General_Notes
#TRIED FLEXTABLE
ft <- flextable(sum_table)
ft <- fontsize(ft, size = 12)
ft <- autofit(ft)
print(ft)
#TRIED KABLE
print(kable(sum_table,"latex"))
}

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)

Strange actual parameter assignment in shiny's renderPlot

When using a for loop to render some plots I obtained results I didn't understand. All plots became equal to the (intended) last one. I hope to make this more clear in the example below. Note the plot1 shows a '6' (the last one), not a '5' (as intended).
Can anyone explain this and/or give a solution avoid this kind of behaviour.
shiny ui:
shinyUI (fluidPage(
fluidRow (
column (6, plotOutput ('plot1', height = "180px")),
column (6, plotOutput ('plot2', height = "180px"))
),
fluidRow (
column (6, plotOutput ('plot3', height = "180px")),
column (6, plotOutput ('plot4', height = "180px"))
)
))
shiny server:
shinyServer (function (input, output, session) {
require (ggplot2)
plotId <- c('plot1', 'plot2', 'plot3', 'plot4')
pw <- initPlotWindows ()
output[['plot1']] <- renderPlot ({pw[[1]]})
output[['plot2']] <- renderPlot ({pw[[2]]})
output[['plot3']] <- renderPlot ({pw[[3]]})
output[['plot4']] <- renderPlot ({pw[[4]]})
id <- 'plot1'
i <- 5
output[[id]] <- renderPlot ({pw[[i]]})
id <- 'plot3'
i <- 6
# output[[id]] <- renderPlot ({pw[[i]]})
})
initPlotWindows <- function () {
pw <- vector (mode = 'list', length = 6) # plot window data
for (i in 1:6) pw[[i]] <- p_empty (plotN = i)
pw
}
p_empty <- function (plotN) {
p <- ggplot()
p <- p + annotate("text", label = plotN, x = .5, y = .5, size = 20, colour = "grey")
p <- p + theme(axis.ticks.x = element_blank(), axis.text.x = element_blank(), axis.title.x=element_blank())
p <- p + theme(axis.ticks.y = element_blank(), axis.text.y = element_blank(), axis.title.y=element_blank())
p
}
Resulting output. Plot1 contains a 6 not a 5!
The reason why this happens is because shiny does not execute your server side code line by line. Shiny executes all of the non-reactive code once at the beginning. But renderPlot() and other reactive code will only run when it is necessary. (when they are called)
So what happened is, it assigned 5, and then 6 to i, and only rendered the plot afterwards.
output[[id]] <- renderPlot ({
print("section D")
pw[[i]]})
You can check it pretty easily in the R console using the print() function:
shinyServer (function (input, output, session) {
print("section A")
require (ggplot2)
plotId <- c('plot1', 'plot2', 'plot3', 'plot4')
pw <- initPlotWindows ()
output[['plot1']] <- renderPlot ({
print("section B1")
pw[[1]]})
output[['plot2']] <- renderPlot ({
print("section B2")
pw[[2]]})
output[['plot3']] <- renderPlot ({
print("section B3")
pw[[3]]})
output[['plot4']] <- renderPlot ({
print("section B4")
pw[[4]]})
print("section C")
id <- 'plot1'
i <- 5
output[[id]] <- renderPlot ({
print("section D")
pw[[i]]})
print("section E")
id <- 'plot3'
i <- 6
# output[[id]] <- renderPlot ({pw[[i]]})
})
Console output:
[1] "section A"
[1] "section C"
[1] "section E"
[1] "section B1"
[1] "section B2"
[1] "section B3"
[1] "section B4"
[1] "section D"
Edit:
As for the output[[id]], id gets evaluated at the beginning, so output[[id]] becomes output[[plot1]]. But pw[[i]] is only evaluated when shiny asks the plot to render, which is after the value has been set to 5 and then to 6.
If you want plot1 to show 5, then you could assign id outside of renderPlot(), and assign i inside of renderPlot():
id <- 'plot1'
output[[id]] <- renderPlot ({
i <- 5
pw[[i]]})
Thank you GyD,
From your answer I conclude that a normal for-loop is not possible. The running variable 'i' would than be defined outside and not inside renderPlot().
So it seems that I have to use eval (parse()) for at least renderPlot().
A for-loop like:
for ( i in 1:4) {
pltId <- paste ('plot', i, sep='')
output[[pltId]] <- renderPlot ({pw[i]})
}
would then become (using eval(parse()) for the whole assignment):
for ( i in 1:4) {
eval (parse (text = paste ("output[['plot", i, "']] <- renderPlot ({pw[", i, "]})", sep='')))
}
Your answer should work, but you could generate both the UI elements and the server side with loops. (don't know if that interests you)
I am not a huge fan of for loops in R, so I'm using lapply.
library(shiny)
library(ggplot2)
# I want to plot these elements
vec <- c(5, 2, 3, 4)
# Defining some functions
initPlotWindows <- function () {
pw <- vector (mode = 'list', length = 6) # plot window data
for (i in vec) pw[[i]] <- p_empty (plotN = i)
pw
}
p_empty <- function (plotN) {
p <- ggplot()
p <- p + annotate("text", label = plotN, x = .5, y = .5, size = 20, colour = "grey")
p <- p + theme(axis.ticks.x = element_blank(), axis.text.x = element_blank(), axis.title.x=element_blank())
p <- p + theme(axis.ticks.y = element_blank(), axis.text.y = element_blank(), axis.title.y=element_blank())
p
}
# Creating pw list
pw <- initPlotWindows()
ui <- fluidPage(
# Creating UI from loop
lapply(vec, function(i) {
column(6, plotOutput(paste0('plot', i), height = "180px"))
})
)
server <- function(input, output, session){
# Generating UI output from loop
lapply(vec, function(i) {
output[[paste0('plot', i)]] <- renderPlot({
pw[[i]]
})
})
}
shinyApp(ui, server)