Hello i am trying to make an app in shiny that will take 3 vectors from a data frame and two entered inputs. I would like the five entries to pass threw the function I have maid below and give the output that the function is maid to give. This would be 4 plots set in a grid (two heat maps, one point plot and a simivariogram). I feel that I have the bulk of the app together but I am having trouble getting my five inputs from the ui to pass threw my function and give out the plots. The function works great in R without shiny i just want it to work as an app now. Also I am pretty new to shiny so i might be missing something simple.
UI:
library(shiny)
library(shinydashboard)
library(ggplot2)
library(leaflet)
library(data.table)
library(dplyr)
################
# App interface
ui <- fluidPage(
# App csv input
headerPanel("Kriging"),
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
tags$hr(),
checkboxInput('header', 'Header', TRUE),
# App button selection for var, lat, lon
fluidRow(
column(6,radioButtons("xaxisGrp","Var:", c("1"="1","2"="2"))),
column(6,checkboxGroupInput("yaxisGrp","Lat/Lon:", c("1"="1","2"="2")))
),
# App buttons comma and quote
radioButtons('sep', 'Separator',
c(Comma=',', Semicolon=';',Tab='\t'), ','),
radioButtons('quote', 'Quote',
c(None='','Double Quote'='"','Single Quote'="'"),'"'),
uiOutput("choose_columns")
),
mainPanel(
tabsetPanel(
tabPanel("Plot",plotOutput("plot")),
tabPanel("Data", tableOutput('contents'))
)
)
# App sliders for values of definition
,
sliderInput(inputId = "num",
label = "choose x",
value = 0.1, min = 0.01, max = 1),
sliderInput(inputId = "num",
label = "choose y",
value = 0.1, min = 0.01, max = 1)
#initiating kriging
, actionButton("btn", "Krige")
)
##################################################
Server:
I have boxed off my function but I need help passing my arguments into the function.
server <- function(input, output, session) {
dsnames <- c()
data_set <- reactive({
inFile <- input$file1
if (is.null(inFile))
return()
data_set<-read.csv(inFile$datapath, header=input$header,
sep=input$sep, quote=input$quote)
})
output$contents <- renderTable({data_set()})
#controlling our buttons
observe({
dsnames <- names(data_set())
cb_options <- list()
cb_options[ dsnames] <- dsnames
updateRadioButtons(session, "xaxisGrp",
label = "Var",
choices = cb_options,
selected = "")
updateCheckboxGroupInput(session, "yaxisGrp",
label = "Lat/Lon",
choices = cb_options,
selected = "")
})
output$choose_dataset <- renderUI({
selectInput("dataset", "Data set", as.list(data_sets))
})
##############################################################
#My function
kri <- function(var, lat, lon, defx, defy){
options(warn = -1)
#internal function for kriging
kri3 <- function(var, lat, lon, defx, defy){
#making a data frame out of the given vector
spdf <- data.frame(var,lat,lon)
#makeing spatial point data frame coords
sp::coordinates(spdf) <- ~ lon + lat
bbox <- sp::bbox(spdf)
#variogram stuff
lzn.vgm <- gstat::variogram(var ~ 1, spdf)
lzn.fit1 <- gstat::fit.variogram(lzn.vgm, model = gstat::vgm(1, "Sph", 900, 1))
lzn.fit = automap::autofitVariogram(var ~ 1,
spdf,
model = c("Sph", "Exp", "Gau", "Ste"),
kappa = c(0.05, seq(0.2, 2, 0.1), 5, 10),
fix.values = c(NA, NA, NA),
start_vals = c(NA,NA,NA),
verbose = T)
#making our grid
cs <- c(defx, defy)
bb <- sp::bbox(spdf)
cc <- bb[,1] + (cs/2)
cd <- ceiling(diff(t(bb))/cs)
gold_grd <- sp::GridTopology(cellcentre.offset = cc, cellsize = cs, cells.dim = cd)
gold_grd
p4s <- sp::CRS(sp::proj4string(spdf))
gold_sg <- sp::SpatialGrid(gold_grd, proj4string = p4s)
summary(gold_sg)
#kringing and auto kriging
lzn.kriged <- as.data.frame(gstat::krige(var ~ 1, spdf, gold_sg , model=lzn.fit1))
lzn.Akriged <- automap::autoKrige(var ~ 1, spdf, gold_sg)
lzn.Akriged.pred <- lzn.Akriged$krige_output$var1.pred
lzn.Akriged.var <- lzn.Akriged$krige_output$var1.var
#making a data frame to use in return
kriw <- data.frame(lzn.kriged, lzn.Akriged.var, lzn.Akriged.pred)
return(kriw)
}
kriw <- kri3(var, lat, lon, defx, defy)
#internal function for maping
Kmap <- function(var, lat, lon, kriw){
#making a data spatial point data frame for out variogram plot
spdf <- data.frame(var,lat,lon)
#makeing spatial point data frame coords
sp::coordinates(spdf) <- ~ lon + lat
bbox <- sp::bbox(spdf)
#variogram stuff
lzn.vgm <- gstat::variogram(var ~ 1, spdf)
lzn.fit = automap::autofitVariogram(var ~ 1,
spdf,
model = c("Sph", "Exp", "Gau", "Ste"),
kappa = c(0.05, seq(0.2, 2, 0.1), 5, 10),
fix.values = c(NA, NA, NA),
start_vals = c(NA,NA,NA),
verbose = T)
varplot <- plot(lzn.vgm, lzn.fit$var_model, main = "Fitted variogram")
#making a dataframe for ggplot
kriw <- as.data.frame(kriw)
#making a maps
bbox1 <- ggmap::make_bbox(lon, lat, f = 1.4)
map <- ggmap::get_map(bbox1)
#making a heat map
M1 <- ggmap::ggmap(map) +
ggplot2::geom_tile(data = kriw, ggplot2::aes(x = lon,
y = lat, alpha = var1.pred), fill = "red") + ggplot2::ggtitle("Prediction Heat Map")
M2 <- ggmap::ggmap(map) +
ggplot2::geom_tile(data = kriw, ggplot2::aes(x = lon,
y = lat, alpha = var1.var), fill = "red") + ggplot2::ggtitle("Variance Heat Map")
var2 <- data.frame(var, lat, lon)
Dplot <- ggmap::ggmap(map) + ggplot2::geom_point(data = var2, ggplot2::aes(size=var, color=var, alpha=var)) +
ggplot2::coord_equal() + ggplot2::ggtitle("Desnisty map") + ggplot2::theme_bw()
#Placing both heat maps together
heat <- gridExtra::grid.arrange(M1,M2,varplot,Dplot, ncol=2)
return(heat)
}
#mapping output
Kmap(var, lat, lon, kriw)
options(warn = 0)
}
###############################################
# end of my fucntion
}
shinyApp(ui = ui, server = server)
What I get
What i want in the plot box
It appears you need a observe to tie this all together. Try this at the end of your server function.
observeEvent(
# react to button press
input$btn,
{
# to show the input values
str(input$xaxisGrp)
str(input$yaxisGrp)
# you have defined num for both x and y
# so I think you will want to change the
# inputId to numX and numY in ui
str(input$num)
# translate all the inputs into
# suitable arguments for kri
# send the output from kri
output$plot <- renderPlot({
kri(...allyourtranslatedargument...)
})
}
)
Related
I'm sorry my code is too complex to create a MRE. I am currently trying to dynamically output n numbers of plots & inputSliders based on the number of calculation columns inputted. I have looked almost everywhere, however I can not seem to find a previously posted question that connects dynamically produced plots & sliders.
Goals: Upload n plots & inputSlider based up a file upload. Two reactive vertical lines on top of the plot that move based on the respective inputSlider range.
What actually happens: The correct number of plots & sliderInputs output, however the inputSliders aren't reactive to the created plots AND the vertical line doesn't appear.
I don't receive any error messages, however I am almost certain that the issues lies in that my inputSlider information returns NULL.
I've tried to change the possible inputs for the ggplot code to hopefully show the respective plots by doing:
...+geom_vline(xintercept = input$plotSlider[1])+ geom_vline(xintercept = input$plotSlider[2])
...+geom_vline(xintercept = output$plotSlider[1])+geom_vline(xintercept = output$plotSlider[2])
..+geom_vline(xintercept = plotSlider[1]) +geom_vline(xintercept = plotSlider[2])
I also have tried rendering the sliders before the plots, since the input variable wouldn't have been created yet.
This here is a sample csv file:
structure(list(X10.9 = c(11.1, 11.6, 12, 12.5, 13, 13.4), X = c(NA,
NA, NA, NA, NA, NA), X.0.095 = c(-0.0911, -0.07, -0.0891, -0.1021,
-0.1019, -0.1019), X.1 = c(NA, NA, NA, NA, NA, NA), X1.4241 = c(1.4396,
1.4439, 1.4454, 1.4498, 1.4513, 1.4513), X.2 = c(NA, NA, NA,
NA, NA, NA), X1.4353 = c(1.4498, 1.4648, 1.474, 1.4819, 1.485,
1.4866), X.3 = c(NA, NA, NA, NA, NA, NA), X0.6736 = c(0.6943,
0.7066, 0.7141, 0.7179, 0.7193, 0.7182)), row.names = c(NA, 6L
), class = "data.frame")
My Code so far:
library(shiny)
library(dplyr, warn.conflicts = FALSE)
library(ggplot2)
#library(MeltR)
library(shiny)
library(glue)
# Define UI ----
ui <- navbarPage(title = "MeltShiny",
id = "navbar",
navbarMenu("File",
tabPanel("Add Data",
fluidPage(
sidebarLayout(
sidebarPanel(
textInput(label="Enter the Pathlength for each Absorbance Reading(separated by commas)",
placeholder = "E.g: 2,5,3,2,...",
inputId = "pathlengths"),
fileInput(label = "Add Data",
inputId = "inputFile",
multiple = FALSE,
accept = ".csv")
),
mainPanel(
tableOutput("contents")
)
)
)
)
),tabPanel(
value = "vizPanel",
title = "Data Visualization",
uiOutput("sliders"),
uiOutput("plots")
)
)
server <- function(input,output){
#Reactive list variable
values <- reactiveValues(masterFrame=NULL,up=NULL,loaded=NULL)
plots <- reactiveValues()
#Upload Project File
upload <- observeEvent(eventExpr =input$inputFile,
handlerExpr = {
req(input$inputFile)
#Declaring variables
pathlengths <- c(unlist(strsplit(input$pathlengths,",")))
req(input$inputFile)
fileName = input$inputFile$datapath
cd <- read.csv(file = fileName,header=FALSE)
df <- cd %>% select_if(~ !any(is.na(.)))
#Creating temporary frame to store sample data
columns <- c("Sample", "Pathlength", "Temperature", "Absorbance")
tempFrame <- data.frame(matrix(nrow = 0, ncol = 4))
colnames(tempFrame) <- columns
readings <- ncol(df)
#Loop that appends sample data
counter <- 1
for (x in 2:readings){
col <- df[x]
sample<-rep(c(counter),times=nrow(df[x]))
pathlength<-rep(c(pathlengths[counter]),times=nrow(df[x]))
col <- df[x]
t <- data.frame(sample,pathlength,df[1],df[x])
names(t) <- names(tempFrame)
tempFrame <- rbind(tempFrame, t)
counter <- counter + 1
}
values$numReadings <- counter-1
values$masterFrame <- tempFrame
values$up <- 1
}
)
output$contents <- renderTable({
return(values$masterFrame)})
observeEvent(eventExpr = input$navbar == "vizPanel",
handlerExpr = {
req(input$inputFile)
print("Observe Triggered")
for(i in 1:values$numReadings){
local({
myI <- i
plotName = paste0("plot",myI)
plotSlider = paste0("plotSlider",myI)
output[[plotName]] <- renderPlot({
data = values$masterFrame[values$masterFrame$Sample == myI,]
ggplot(data, aes(x = Temperature,
y = Absorbance,
color = factor(Sample))) +geom_point() +theme_classic()+geom_vline(xintercept = input$plotSlider[1]) +geom_vline(xintercept = input$plotSlider[2])
})
})
values$loaded <- 1
}
}
)
output$plots <- renderUI({
req(values$loaded)
plot_output_list <- lapply(1:values$numReadings, function(i){
plotName <- paste0("plot",i)
plotOutput(plotName,height=280,width=250)
})
do.call(tagList,plot_output_list)
})
output$sliders <- renderUI({
req(input$inputFile)
print("slider")
slider_output_list <- lapply(1:values$numReadings, function(i){
plotSlider <- paste0("plotSlider",i)
data = values$masterFrame[values$masterFrame$Sample == i,]
xmin = min(data$Temperature)
xmax = max(data$Temperature)
sliderInput(plotSlider,"Range of values",min=xmin,max=xmax,value=c(xmin,xmax))
})
do.call(tagList,slider_output_list)
})
}
# Run the app
shinyApp(ui = ui, server = server)
Any suggestions would be greatly appreciated!
Appropriate syntax for input$plotSlider will make it work. Try this
library(shiny)
library(dplyr, warn.conflicts = FALSE)
library(ggplot2)
#library(MeltR)
library(shiny)
library(glue)
# Define UI ----
ui <- navbarPage(title = "MeltShiny",
id = "navbar",
navbarMenu("File",
tabPanel("Add Data",
fluidPage(
sidebarLayout(
sidebarPanel(
textInput(label="Enter the Pathlength for each Absorbance Reading(separated by commas)",
placeholder = "E.g: 2,5,3,2,...",
inputId = "pathlengths"),
fileInput(label = "Add Data",
inputId = "inputFile",
multiple = FALSE,
accept = ".csv")
),
mainPanel(
tableOutput("contents")
)
)
)
)
),tabPanel(
value = "vizPanel",
title = "Data Visualization",
uiOutput("sliders"),
uiOutput("plots")
)
)
server <- function(input,output){
#Reactive list variable
values <- reactiveValues(masterFrame=NULL,up=NULL,loaded=NULL)
plots <- reactiveValues()
#Upload Project File
upload <- observeEvent(eventExpr =input$inputFile,
handlerExpr = {
req(input$inputFile)
#Declaring variables
pathlengths <- c(unlist(strsplit(input$pathlengths,",")))
req(input$inputFile)
fileName = input$inputFile$datapath
cd <- read.csv(file = fileName,header=TRUE)
df <- cd %>% select_if(~ !any(is.na(.)))
#Creating temporary frame to store sample data
columns <- c("Sample", "Pathlength", "Temperature", "Absorbance")
tempFrame <- data.frame(matrix(nrow = 0, ncol = 4))
colnames(tempFrame) <- columns
readings <- ncol(df)
#Loop that appends sample data
counter <- 1
for (x in 2:readings){
# local({
# x <- x
col <- df[x]
sample<-rep(c(counter),times=nrow(df[x]))
pathlength<-rep(c(pathlengths[counter]),times=nrow(df[x]))
col <- df[x]
t <- data.frame(sample,pathlength,df[1],df[x])
names(t) <- names(tempFrame)
tempFrame <- rbind(tempFrame, t)
counter <- counter + 1
#})
}
values$numReadings <- counter-1
values$masterFrame <- tempFrame
values$up <- 1
}
)
output$contents <- renderTable({
return(values$masterFrame)})
# observeEvent(eventExpr = input$navbar == "vizPanel",
# handlerExpr = {
observe({
req(input$inputFile)
#print(input[[paste0("plotSlider1")]])
print("Observe Triggered")
for(i in 1:values$numReadings){
local({
myI <- i
plotName = paste0("plot",myI)
plotSlider = paste0("plotSlider",myI)
output[[plotName]] <- renderPlot({
data = values$masterFrame[values$masterFrame$Sample == myI,]
ggplot(data, aes(x = Temperature,
y = Absorbance,
color = factor(Sample))) +
geom_point() + theme_classic()+
geom_vline(xintercept = input[[paste0("plotSlider",myI)]][1]) +
geom_vline(xintercept = input[[paste0("plotSlider",myI)]][2])
})
})
values$loaded <- 1
}
})
output$plots <- renderUI({
req(values$loaded)
plot_output_list <- lapply(1:values$numReadings, function(i){
plotName <- paste0("plot",i)
plotOutput(plotName,height=280,width=250)
})
do.call(tagList,plot_output_list)
})
output$sliders <- renderUI({
req(input$inputFile)
slider_output_list <- lapply(1:values$numReadings, function(i){
plotSlider <- paste0("plotSlider",i)
data = values$masterFrame[values$masterFrame$Sample == i,]
xmin = min(data$Temperature)
xmax = max(data$Temperature)
sliderInput(plotSlider,"Range of values",min=xmin,max=xmax,value=c(xmin,xmax))
})
do.call(tagList,slider_output_list)
})
}
# Run the app
shinyApp(ui = ui, server = server)
I built a shiny app which present several plot types. However, the plots are cut from the top, and they are too wide. I tried modifying the width and height in the plotOutput function, did not work.
My code:
ui <- fluidPage(theme = shinytheme('united'),
titlePanel(title = h3("Graphs - ordered chronologically", align="center")),
selectInput("Plot",
"Choose what plots to present",
choices = list(Heatmap = "Heatmap", PCA = "PCA", VolcanoPlot = "VolcanoPlot", GSEA = 'GSEA')),
submitButton(text = "Show plots"),
verticalLayout( plotOutput(outputId = "PART.1", width = '70%'))
)
The problem is most prominent with the Heatmaps and Volcano plots. The volcano plot is cut from the top, and the heatmaps are too stretched wide:
How can I fix this? thank you.
EDIT:
A minimal version of my code:
library(data.table)
library(dplyr)
library(shiny)
library(shinythemes)
library(plotly)
library(compGenomRData)
library(BiocManager)
library(DESeq2)
library(org.Hs.eg.db)
library(TxDb.Hsapiens.UCSC.hg19.knownGene)
library(EnsDb.Hsapiens.v86)
library(AnnotationHub)
library(AnnotationDbi)
library(pheatmap)
library(EnhancedVolcano)
library(ggplot2)
library(FactoMineR)
library(devtools)
library(clusterProfiler)
library(ggnewscale)
library(enrichplot)
library(msigdbr)
library(readxl)
library(ExperimentHub)
library(annotate)
ui <- fluidPage(theme = shinytheme('united'),
titlePanel(title = h3("Graphs - ordered chronologically", align="center")),
selectInput("Plot",
"Choose which plots to present",
choices = list(Heatmap = "Heatmap", PCA = "PCA", VolcanoPlot = "VolcanoPlot", GSEA = 'GSEA')),
submitButton(text = "Show plots"),
verticalLayout( plotOutput(outputId = "PART.1", width = '70%'),
plotOutput(outputId = "PART.2", width = '70%'),
plotOutput(outputId = "PART.3", width = '70%'),
plotOutput(outputId = "PART.4", width = '70%'),
plotOutput(outputId = "PART.5", width = '70%'),
plotOutput(outputId = "PART.6", width = '70%'),
plotOutput(outputId = "PART.7", width = '70%'))
)
server <- function(input, output) {
# RNA-seq data
raw_counts <- frea
d('E-MTAB-7805-raw-counts.tsv', data.table = F)
metadata <- fread('E-MTAB-7805-experiment-design.tsv' ,data.table = F)
A=duplicated(raw_counts$`Gene ID`) # Check for duplicates and remove them
raw_counts = raw_counts[!A,]
A=duplicated(raw_counts$`Gene Name`) # Check for duplicates and remove them
raw_counts = raw_counts[!A,]
Hugo.Symbol <- raw_counts[,c(1:2)]
rownames(raw_counts) <- raw_counts$`Gene Name` # renaming rownames
raw_counts <- raw_counts[, -c(1:2)]
# metadata
C = duplicated(metadata$Run) # Check for duplicates and remove them
metadata = metadata[!C,]
rownames(metadata) <- metadata$Run
metadata <- metadata[,-1]
ind <- order(colnames(raw_counts), rownames(metadata))
raw_counts <- raw_counts[,ind]
# filter
target1 <- c("0 day", "1 day")
Meta_filter1 <- metadata %>% dplyr::filter(`Factor Value[time]` %in% target1)
Counts_filter1 <- raw_counts[intersect(names(raw_counts), rownames(Meta_filter1))]
rownames(Counts_filter1) <- Hugo.Symbol$`Gene Name`
# annotate
Meta_filter1$group <- plyr::mapvalues(Meta_filter1$`Factor Value[time]`, c("0 day", "1 day"),
c("CTRL", "CASE"))
ind <- order(colnames(Counts_filter1), rownames(Meta_filter1))
Counts_filter1 <- Counts_filter1[,ind]
dds <- DESeqDataSetFromMatrix(countData = Counts_filter1,
colData = Meta_filter1,
design = ~ group)
dds = DESeq(dds)
res = results(dds)
res$symbol <- rownames(res)
resOrder <- res[order(res$padj),]
# heatmap
dds.symbol = dds
rownames(dds.symbol) = mapIds(org.Hs.eg.db,
keys=rownames(dds),
column="SYMBOL",
keytype="SYMBOL",
multiVals="first")
rownames(dds.symbol)[is.na(rownames(dds.symbol))] = rownames(dds)[is.na(rownames(dds.symbol))]
rownames(dds.symbol) = make.unique(rownames(dds.symbol))
selectUp <- resOrder$symbol[resOrder$log2FoldChange>0][1:20]
selectDown <- resOrder$symbol[resOrder$log2FoldChange<0][1:20]
select = c(selectUp,selectDown)
df <- data.frame(row.names = colnames(dds.symbol),
group = colData(dds.symbol)$group)
normcounts = assay(vst(dds.symbol,blind=T, nsub = 2000))
# Functional enrichment
res = res[!is.na(res1$padj),]
mygenes <- rownames(res)
lfc = res1$log2FoldChange # get gene symbol
names(lfc) <- rownames(res)
lfc <- sort(lfc, decreasing = TRUE)
hallmarks <- msigdbr(species = "Homo sapiens", category = "H") %>%
dplyr::select(gs_name, gene_symbol)
## Output
output$PART.1 <- renderPlot({
if (input$Plot == 'Heatmap') {
pheatmap(normcounts[select,], cluster_rows=TRUE,
show_colnames = FALSE,cluster_cols=TRUE,
annotation_col=df, scale = 'row',cutree_cols = 2,cutree_rows = 2)
} else if (input$Plot == 'PCA') {
Var <- apply(normcounts, 1, var)
selectedVarGenes <- names(Var[order(Var, decreasing = T)][1:1000])
M <- t(normcounts[selectedVarGenes,])
pcaResults = prcomp(M)
qplot(pcaResults$x[,1],pcaResults$x[,2], col=dds1$group,size=2)
} else if (input$Plot == 'VolcanoPlot') {
EnhancedVolcano(resOrder,
lab = resOrder$symbol,
x = 'log2FoldChange',
y = 'padj',
labSize=4,
FCcutoff=2 )
} else {
em <- GSEA(lfc, TERM2GENE = hallmarks)
dotplot(em)
}
})
shinyApp(ui = ui, server = server)
Maybe if you include a call to par before calling pheatmap can help:
par(mar=c(5,4,6,2)) # bottom, left, top, right
pheatmap(
normcounts[select,], cluster_rows=TRUE,
show_colnames = FALSE, cluster_cols=TRUE,
annotation_col=df, scale = 'row',
cutree_cols = 2,cutree_rows = 2
)
Thanks for your help in advance as this one is really driving me mad. I am trying to create a plotly scatterplot where I can change the location of single plots by dragging them, thus changing the regression line. Importantly, I would like to filter the data through a pickerInput, to only run the analysis for a subset of the data.
Most things are working, however I am coming unstuck with my use of reactiveValues(). More, specifically, I believe reactiveValues() can't take a reactive dataframe...in this case a filtered version of mtcars. I have tried all sorts of things and am now getting a little desperate. Below is the code. I have also attached code of a simplified version of the code, which works just fine however doesn't have the all important filtering capability.
Please help!
library(plotly)
library(purrr)
library(shiny)
ui = navbarPage(windowTitle="Draggable Plot",
tabPanel(title = "Draggable Plot",
sidebarPanel(width = 2,
pickerInput("Cylinders","Select Cylinders",
choices = unique(mtcars$cyl), options = list(`actions-box` = TRUE),multiple = FALSE, selected = unique(mtcars$cyl))),
mainPanel(
plotlyOutput("p", height = "500px", width = "1000px"),verbatimTextOutput("summary"))))
server <- function(input, output, session) {
data = reactive({
data = mtcars
data <- data[data$cyl %in% input$Cylinders,]
return(data)
})
rv <- reactiveValues(
data = data()
x = data$mpg,
y = data$wt
)
grid <- reactive({
data.frame(x = seq(min(rv$x), max(rv$x), length = 10))
})
model <- reactive({
d <- data.frame(x = rv$x, y = rv$y)
lm(y ~ x, d)
})
output$p <- renderPlotly({
# creates a list of circle shapes from x/y data
circles <- map2(rv$x, rv$y,
~list(
type = "circle",
# anchor circles at (mpg, wt)
xanchor = .x,
yanchor = .y,
# give each circle a 2 pixel diameter
x0 = -4, x1 = 4,
y0 = -4, y1 = 4,
xsizemode = "pixel",
ysizemode = "pixel",
# other visual properties
fillcolor = "blue",
line = list(color = "transparent")
)
)
# plot the shapes and fitted line
plot_ly() %>%
add_lines(x = grid()$x, y = predict(model(), grid()), color = I("red")) %>%
layout(shapes = circles) %>%
config(edits = list(shapePosition = TRUE))
})
output$summary <- renderPrint({a
summary(model())
})
# update x/y reactive values in response to changes in shape anchors
observe({
ed <- event_data("plotly_relayout")
shape_anchors <- ed[grepl("^shapes.*anchor$", names(ed))]
if (length(shape_anchors) != 2) return()
row_index <- unique(readr::parse_number(names(shape_anchors)) + 1)
pts <- as.numeric(shape_anchors)
rv$x[row_index] <- pts[1]
rv$y[row_index] <- pts[2]
})
}
shinyApp(ui, server)
Just to add insult to injury, this version of the code without filtering works just fine.
library(plotly)
library(purrr)
library(shiny)
ui = navbarPage(windowTitle="Draggable Plot",
tabPanel(title = "Draggable Plot",
mainPanel(
plotlyOutput("p", height = "500px", width = "1000px"))))
server <- function(input, output, session) {
rv <- reactiveValues(
x = mtcars$mpg,
y = mtcars$wt
)
grid <- reactive({
data.frame(x = seq(min(rv$x), max(rv$x), length = 10))
})
model <- reactive({
d <- data.frame(x = rv$x, y = rv$y)
lm(y ~ x, d)
})
output$p <- renderPlotly({
# creates a list of circle shapes from x/y data
circles <- map2(rv$x, rv$y,
~list(
type = "circle",
# anchor circles at (mpg, wt)
xanchor = .x,
yanchor = .y,
# give each circle a 2 pixel diameter
x0 = -4, x1 = 4,
y0 = -4, y1 = 4,
xsizemode = "pixel",
ysizemode = "pixel",
# other visual properties
fillcolor = "blue",
line = list(color = "transparent")
)
)
# plot the shapes and fitted line
plot_ly() %>%
add_lines(x = grid()$x, y = predict(model(), grid()), color = I("red")) %>%
layout(shapes = circles) %>%
config(edits = list(shapePosition = TRUE))
})
output$summary <- renderPrint({a
summary(model())
})
# update x/y reactive values in response to changes in shape anchors
observe({
ed <- event_data("plotly_relayout")
shape_anchors <- ed[grepl("^shapes.*anchor$", names(ed))]
if (length(shape_anchors) != 2) return()
row_index <- unique(readr::parse_number(names(shape_anchors)) + 1)
pts <- as.numeric(shape_anchors)
rv$x[row_index] <- pts[1]
rv$y[row_index] <- pts[2]
})
}
shinyApp(ui, server)
The following should address your concerns.
rv <- reactiveValues()
observe({
rv$data = data()
rv$x = data()$mpg
rv$y = data()$wt
})
I have a question about the checkboxInput in R shiny. When it is checked, the scatter plot should be colorful while when it is unchecked, the plot should be black. I have tried several methods, but it keeps colorful no matter whether it is checked or not. Could you please help me with fix the code? Thanks so much.
library(shiny)
library(dplyr)
library(ggplot2)
# Start a 'Shiny' part
shinyServer(function(input, output, session) {
# Create a new reactive variable
newVar <- reactive({
newData <- msleep %>% filter(vore == input$vore)
})
# Create a scatter plot
output$sleepPlot <- renderPlot({
newDat <- newVar()
g <- ggplot(newDat, aes(x = bodywt, y = sleep_total))
g + geom_point(size = input$size, aes(col = conservation))
})
# Create text info
output$info <- renderText({
newDat <- newVar()
paste("The average body weight for order", input$vore, "is", round(mean(newDat$bodywt, na.rm = TRUE), 2),
"and the average total sleep time is", round(mean(newDat$sleep_total, na.rm = TRUE), 2), sep = " ")
})
# Create output of observations
output$table <- renderTable({
newDat <- newVar()
newDat
})
})
library(ggplot2)
shinyUI(fluidPage(
# Application title
titlePanel("Investigation of Mammal Sleep Data"),
# Sidebar with options for the data set
sidebarLayout(
sidebarPanel(
h3("Select the mammal's biological order:"),
selectizeInput("vore", "Vore", selected = "omni",
choices = levels(as.factor(msleep$vore))),
br(),
sliderInput("size", "Size of Points on Graph",
min = 1, max = 10, value = 5, step = 1),
checkboxInput("conservation", h4("Color Code Conservation Status", style = "color:red;"))
),
# Show output
mainPanel(
plotOutput("sleepPlot"),
textOutput("info"),
tableOutput("table")
)
)
))
Try this
# Create a scatter plot
output$sleepPlot <- renderPlot({
newDat <- newVar()
colorme <- unique(newVar()$conservation)
ncolor <- length(colorme)
if (!input$conservation) {
mycolor <- c(rep("black",ncolor))
mylabels <- c(rep(" ",ncolor))
}
g <- ggplot(newDat, aes(x = bodywt, y = sleep_total)) +
geom_point(size = input$size, aes(col = conservation)) +
{if (!input$conservation) scale_color_manual(name=" ", values=mycolor, labels=mylabels)} +
{ if (!input$conservation) guides(color='none')}
g
})
You can adjust, as necessary.
I'd like to include the reactive outputs of two data sets as different geom_lines in the same ggplotly figure. The code runs as expected when only one reactive data.frame is included as a geom_line. Why not two?
ui <- fluidPage(
sidebarLayout(
selectInput("Var1",
label = "Variable", #DATA CHOICE 1
selected = 10,
choices = c(10:100)),
selectInput("Var1",
label = "Variable2", #DATA CHOICE 2
selected = 10,
choices = c(10:100))
# Show a plot of the generated distribution
),
mainPanel(
plotlyOutput('plot') #Draw figure
)
)
server <- function(input, output) {
out <- reactive({
data.frame(x = rnorm(input$Var1), #Build data set 1
y = 1:input$Var1)
})
out2 <- reactive({
data.frame(x = rnorm(input$Var2), #Build data set 2
y = 1:input$Var2)
})
output$plot <- renderPlotly({
p <- ggplot() +
geom_line(data = out(), aes(x = x, y = y)) #Add both data sets in one ggplot
geom_line(data = out2(), aes(x = x, y = y), color = "red")
ggplotly(p)
})
}
# Run the application
shinyApp(ui = ui, server = server)
When you put the data into long format and give each group a group identifier it seems to work. Note that you should be able to change sliderInput back to selectInput - this was one of the entries I toggled during testing, but the choice of UI widget should not matter.
This works -- code can be simplified inside the reactive from here:
library(plotly)
ui <- fluidPage(
sidebarLayout(
sliderInput("Var1",
label = "Variable", #DATA CHOICE 1
min=10, max=100, value=10),
sliderInput("Var2",
label = "Variable2", #DATA CHOICE 2
min=10, max=100, value=10),
),
mainPanel(
plotlyOutput('plot') #Draw figure
)
)
server <- function(input, output) {
out <- reactive({
x1 <- rnorm(input$Var1)
y1 <- seq(1:input$Var1)
x2 <- rnorm(input$Var2)
y2 <- seq(1:input$Var2)
xx <- c(x1,x2)
yy <- c(y1,y2)
gg <- c( rep(1,length(y1)), rep(2,length(y2)) )
df <- data.frame(cbind(xx,yy,gg))
df
})
output$plot <- renderPlotly({
p <- ggplot() +
geom_line(data=out(), aes(x = xx, y = yy, group=gg, colour=gg))
ggplotly(p)
})
}
shinyApp(ui = ui, server = server)