I'm trying to understand how ggvis works in the context of shiny and it's been a real headache. At this point I'm just trying to make something, anything interactive. Ideally I would like to be able to filter data points with sliders and be able to click on sectors and links to zoom and highlight respectively.
Ignoring the entire right bar, how would I be able to implement ggvis?
server.r
options(shiny.maxRequestSize=60*1024^2)
# Option to use scientific notation
options(scipen=999)
library(ggplot2)
library(ggvis)
shinyServer(function(input, output) {
inputData <- try(reactive({
inFile <- input$file1
if(is.null(inFile$datapath)){
return(iris)
}
newData <- read.csv(inFile$datapath, fill=TRUE)
newData
}))
output$choose_histVar <- renderUI({
newData <- inputData()
nameDataNew1<-c("ALL" ,"Earmarks", "Free-Cash")
if(class(nameDataNew1)!="try-error"){
selectInput("histVar", "1. Select Funding", as.list(nameDataNew1),
multiple = FALSE)
}
else{
selectInput("histVar", "1.Select Funding", NULL, multiple = FALSE)
}
})
# Use renderTable() function to render a table
output$summaryTable <- renderTable({ summary( try(inputData()) ) })
output$plot.hist <- renderPlot({
plotHistograms(data=try(inputData()), getCol=input$histVar,
getBin=input$bins)
})
output$plot.bar <- renderPlot({ plotcir(data)})
})
plotcir <- function(data) {
set.seed(999)
n = 1000
df = data.frame(factors = sample(letters[1:8], n, replace = TRUE),
x = rnorm(n), y = runif(n))
data.temp <- as.data.frame(df)
circos.par("track.height" = 0.1)
circos.initialize(factors = df$factors, x = df$x)
circos.track(factors = df$factors, y = df$y,
panel.fun = function(x, y) {
circos.text(CELL_META$xcenter, CELL_META$cell.ylim[2] + uy(5,
"mm"),
CELL_META$sector.index)
circos.axis(labels.cex = 0.6)
})
col = rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(df$factors, df$x, df$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "text", sector.index = "a", track.index = 1)
bgcol = rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(df$factors, df$x, bin.size = 0.2, bg.col = bgcol, col = NA)
circos.track(factors = df$factors, x = df$x, y = df$y,
panel.fun = function(x, y) {
ind = sample(length(x), 10)
x2 = x[ind]
y2 = y[ind]
od = order(x2)
circos.lines(x2[od], y2[od])
})
##vis <- reactive({})
circos.link("a", 0, "b", 0, h = 0.4)
circos.link("c", c(-0.5, 0.5), "d", c(-0.5,0.5), col = "red",
border = "blue", h = 0.2)
circos.link("e", 0, "g", c(-1,1), col = "green", border = "black", lwd = 2,
lty = 2)
}
ui.r
# Load libraries used in this Shiny App
library(shiny)
library(ggplot2)
library(circlize)
library(ggvis)
library(shinythemes)
shinyUI(fluidPage(
titlePanel(title = h2("The Wall", align="center")),
theme = shinytheme("cyborg"),
sidebarPanel(
fileInput('file1', 'The default dataset is df data. You may choose your own
CSV file'),
sliderInput('file1', 'Mission 1', value = 10, min = 0, max = 100, step = 1,
post = "%"),
sliderInput('file1', 'Mission 2', value = 0, min = 0, max = 100, step = 1,
post = "%"),
sliderInput('file1', 'Mission 3', value = 0, min = 0, max = 100, step = 1,
post = "%"),
sliderInput('file1', 'Mission 4', value = 0, min = 0, max = 100, step = 1,
post = "%"),
sliderInput('file1', 'Mission 5', value = 0, min = 0, max = 100, step = 1,
post = "%"),
uiOutput("choose_histVar"),
uiOutput("choose_xVar"),
uiOutput("choose_yVar"),
uiOutput("choose_cateVar"),
uiOutput("choose_barVar"),
p()
),
mainPanel(
h3('DOS - Augmented decisions'),
tabsetPanel(type="tab",
tabPanel( "Optimal",
plotOutput('plot.bar')
),
tabPanel("Histogram",
h4(checkboxInput("showHideHistograms", "Show/hide histograms",
value=FALSE)),
# Add a conditional panel to plot the histogram only when "Show
histogram" is checked
conditionalPanel(
condition = "input.showHideHistograms",
# Use plotOutput function to plot the output visualization
plotOutput('plot.hist')
)
)
),
p('')
)
))
Related
I want to calculate the distance of the segment between 2 clicked points, i already have a function with that launches a shiny dashboard that allows you to save the clicks and draw a line between the pairs. It is printing the dimension of the image in pixels. Any image can be used changing the image_path.
I want to know if there is a way to select the segments of each pair and calculate the distance between them in pixels and later convert it to cm.
library(shiny)
library(shinydashboard)
library(dplyr)
library(imager)
library(reactable)
click_length <- function(image_path = system.file("example_images", package = "ClickMetrics")){
app <- shinyApp(
ui <- dashboardPage(
skin = 'purple',
dashboardHeader(title = "ClickMetrics"),
dashboardSidebar(disable = TRUE),
dashboardBody(
fluidRow(
box(plotOutput("IMG",
height = 400,
click = "click_plot")),
box(
(selectInput("IMAGE",
"Images:",
list.files(path = image_path,
pattern = ".jpg",
full.names = TRUE,
include.dirs = FALSE)))
),
actionButton("clear","Clear Points"),
reactableOutput("INFO")
)
)
),
server <- function(input, output, session){
# Creating a reactive value that receives image input
img <- reactive({
f <- input$IMAGE
imager::load.image(f)
})
# Store reactive values for coordinates
CLICKS <- reactiveValues(
x = NULL,
y = NULL,
n = NULL,
pair = NULL
)
ns <- session$ns
observeEvent(eventExpr = input$click_plot$x, handlerExpr = { ## Adds the info about clicks
CLICKS$x <- append(CLICKS$x, input$click_plot$x)
CLICKS$y <- append(CLICKS$y, input$click_plot$y)
CLICKS$n <- append(CLICKS$n, length(CLICKS$x))
CLICKS$pair <-
append(CLICKS$pair,
as.integer(ceiling(length(CLICKS$x)/2)))
df <- data.frame(CLICKS$x, CLICKS$y, CLICKS$pair)
df <- split(df, CLICKS$pair)
print(dim(img())) # prints dimensions of the image
})
output$IMG <- renderPlot({
expr = {
img <- img()
par(mar = c(0.5, 0.5, 1.75, 0.5))
plot(img, axes = FALSE)
box(col = 'gray')
mtext(text = input$IMAGE,
side = 3,
line = 0.5,
adj = 0.5,
cex = 1.23)
if (!is.null(CLICKS$x) && length(CLICKS$x) > 0) {
points(x = CLICKS$x,
y = CLICKS$y,
pch = 19,
cex = 0.75,
col = "red")
text(x = CLICKS$x,
y = CLICKS$y,
label = CLICKS$n,
pos = 3)
n_par <- 2 * floor(length(CLICKS$x)/2)
tb_pairs <- cbind(
matrix(CLICKS$x[1:n_par], ncol = 2, byrow = TRUE),
matrix(CLICKS$y[1:n_par], ncol = 2, byrow = TRUE))
segments(x0 = tb_pairs[, 1],
x1 = tb_pairs[, 2],
y0 = tb_pairs[, 3],
y1 = tb_pairs[, 4],
col = "black")
}
}
})
output$INFO <- renderReactable({
df1 <- data.frame(round(CLICKS$x,2), round(CLICKS$y,2), CLICKS$pair)
reactable(df1)
})
observe({ # clear clicked points
if(input$clear>0){
session$reload()
}
})
})
runApp(app)
}
click_length()
I tried some examples using locator, but it does not work inside a shiny dashboard, which i need.
I am trying to create a dashboard in Shiny. I am taking inputs(data frame - df1) from a user and do some prediction and display the results of the prediction as well as a plot of air quality parameters.
Below is the ui code chunk -
########## User interface ############
ui <- dashboardPage(
dashboardHeader(title = "Air Quality Index"),
dashboardSidebar(
selectizeInput(
"City", "Select the City:",
choices = list("Mumbai", "Delhi", "Bengaluru")
),
numericInput("PM2.5", "PM2.5 Levels:", min = 0, max = 1000, value = 50),
numericInput("PM10", "PM10 Levels:", min = 0, max = 1000, value = 50),
numericInput("NO", "NO Levels:", min = 0, max = 1000, value = 50),
numericInput("CO", "CO Levels:", min = 0, max = 1000, value = 50),
numericInput("NO2", "NO2 Levels:", min = 0, max = 1000, value = 50),
numericInput("O3", "O3 Levels:", min = 0, max = 1000, value = 50),
actionButton("submitbutton", "Calculate AQI", class = "btn btn-primary")
),
dashboardBody(
fluidRow(
valueBoxOutput("AQI"),
valueBoxOutput("high_risk_params")
),
fluidRow(
box(title = "Polluting Contents in Air:", solidHeader = TRUE,
width = 12, collapsible = TRUE,
plotlyOutput("param_plot"))
)
))
And the code for server is -
########### Server logic ############
server <- function(input, output, session) {
# Input Data
datasetInput <- reactive({
df1 <- data.frame(
Names= c("City"= input$City,
"PM2.5"= input$PM2.5,
"PM10"= input$PM10,
"NO"= input$NO,
"NO2"= input$NO2,
"CO"= input$CO,
"O3"= input$O3
),
stringsAsFactors = FALSE)
n <- rownames(df1)
input <- data.table::transpose(df1)
colnames(input) <- n
input[,2:7] <- as.numeric(input[,2:7])
predicted <- data.frame(Predicted.AQI=predict(rf_model_new,input))
print(predicted)
})
output$param_plot <- renderPlotly({
df1 <- data.table::transpose(df1, keep.names = "rn")
df1 <- df1[-1,]
print(df1)
plot <- ggplot(df1) +
geom_col(aes(x = rn, y = as.numeric(V1), fill = as.numeric(V1))) +
labs(x = "Air Paramteres", y = "Value") +
theme_gray() +
ylim(0, NA) +
geom_hline(yintercept = 50) +
scale_fill_gradient(low = "green",
high = "red",
limits = c(0, 300),
na.value = "darkred",
name = "Value") +
theme(panel.background = element_rect(fill = "mintcream"),
legend.position = "none")
plot <- ggplotly(plot)
plot
})
output$AQI <- renderValueBox({
valueBox(paste0( "AQI: ",round(predicted,0)),
" ", icon = icon("cloudscale"), color = "blue", width = 10)
})
output$high_risk_params <- renderValueBox({
risk_df <- df1 %>%
filter(df1[,2:7]> 100)
if(nrow(risk_df)>0){
valueBox("Over Safe Limits", HTML(paste0(risk_df$rn, sep= "<br>")),
icon = icon("exclamation-triangle"), color = "red")
}
else{
valueBox("No Hazard", icon = icon("exclamation-triangle"), color = "green")
}
})
}
Now the error showing is -
Warning: Error in data.table::transpose: object 'df1' not found &
Warning: Error in paste0: object 'predicted' not found &
Warning: Error in filter: object 'df1' not found
Attaching screenshot of the errors.
Any help is much appreciated. Thanks!
https://i.stack.imgur.com/4ncQq.png
try to declare df1 var outside the reactive({}) function and make it global across the whole server and then use it below inside the renderPlotly({}) function
I need to create a plotly plot in shiny that consists of subplots, which will be dynamically created with a changing number of rows (but only ever 2 plots per row). I would like each subplot to be the same size, and to have some space between all the subplots so that nothing overlaps, and to have the legend centred above the entire plot.
However, when more rows of subplots are added, the spacing between the legend and the subplots and between the rows of subplots, goes out of whack. It looks worse the more rows I add. Is there some trick to make subplots look nice and standardised in shiny, when the number of rows is dynamic?
I've inserted an example shiny app below, where you can change the number of rows, subplot margins, and vertical positioning of the legend. This is the basic formatting of what my plot will be - does anyone have any suggestions as to how to fix and standardise how the subplots and legend are arranged?
library(shiny)
library(plotly)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
width = 2,
numericInput(inputId = "left", label = "left", value = 0.05, min = 0),
numericInput(inputId = "right", label = "right", value = 0.05, min = 0),
numericInput(inputId = "top", label = "top", value = 0.05, min = 0),
numericInput(inputId = "bottom", label = "bottom", value = 0.05, min = 0),
numericInput(inputId = "legend", label = "legend", value = 1.2, min = 0),
numericInput(inputId = "rows", label = "rows", value = 1, min = 1)
),
mainPanel(
width = 10,
plotlyOutput("plot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
output$plot <- renderPlotly({
rows <- input$rows
plot <- plot_ly(height = 400*rows)
plot <- add_trace(plot, data = economics, x = ~date, y = ~uempmed)
plot <- layout(
plot,
annotations = list(text = HTML("<b>title</b>"), showarrow = FALSE,
xref = 'x', x = 0.5, yref ='paper', y = 1.1),
legend = list(orientation = "h",
xanchor = "center", x = 0.5,
yanchor = "center", y = input$legend)
)
plots <- c()
for (x in 1:(rows*2)) {
plots[[x]] <- plot
}
subplot(plots, nrows = rows, shareY = FALSE, shareX = FALSE, titleY = TRUE, titleX = FALSE,
margin = c(input$left, input$right, input$top, input$bottom))
})
}
# Run the application
shinyApp(ui = ui, server = server)
One way to address your issue is to define the legend position, heights and margins to be dependent on the number of rows. Try this
server <- function(input, output) {
output$plot <- renderPlotly({
rows <- input$rows
mylegend <- 1 + 1/(5*rows)
myht <- c()
if (rows==1) {
myht <- c(1)
rowsd <- 1
}else {
rowsd <- rows-1
myht <- 1/rows
for (i in 2:rows) {
myht <- c(myht,1/rows)
if (i >3) rowsd <- rows - 1 - (i/3)
}
}
plot <- plot_ly(height = 400*rows)
plot <- add_trace(plot, data = economics, x = ~date, y = ~uempmed)
plot <- layout(
plot,
annotations = list(text = HTML("<b>title</b>"), showarrow = FALSE,
xref = 'x', x = 0.5, yref ='paper', y = 1.1),
legend = list(orientation = "h",
xanchor = "center", x = 0.5,
yanchor = "center", y = mylegend) # input$legend)
)
plots <- c()
for (x in 1:(rows*2)) {
plots[[x]] <- plot
}
subplot(plots, nrows = rows, shareY = FALSE, shareX = FALSE, titleY = TRUE, titleX = FALSE, # heights=myht,
margin = c(input$left, input$right, input$top/rowsd, input$bottom/rowsd)
)
})
}
I modified the interactive R Shiny plot from the R Shiny gallery to plot an interactive standard curve. I would like to plot the interactive plot without using ggplot2 library with just using R base plotting functions.
library(ggplot2)
XYdata <- data.frame(cbind(Values = c(91.8, 95.3, 99.8, 123.3, 202.9, 619.8, 1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
Concn = c(1000, 300, 100, 30, 10, 3, 1, 0.3, 0.1, 0.03, 0.01, 0)))
ui <- fluidPage(
fluidRow(
column(width = 6,
plotOutput("plot1", height = 350,
click = "plot1_click",
brush = brushOpts(
id = "plot1_brush"
)
),
actionButton("exclude_toggle", "Toggle points"),
actionButton("exclude_reset", "Reset")
)
)
)
server <- function(input, output) {
# For storing which rows have been excluded
vals <- reactiveValues(
keeprows = rep(TRUE, nrow(XYdata))
)
NonScientific <- function(l) {l <- format(l, scientific = FALSE); parse(text=l)}
output$plot1 <- renderPlot({
# Plot the kept and excluded points as two separate data sets
XYdata <- data.frame(cbind(Values = c(91.8, 95.3, 99.8, 123.3, 202.9, 619.8, 1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
Concn = c(1000, 300, 100, 30, 10, 3, 1, 0.3, 0.1, 0.03, 0.01, 0)))
keep <- XYdata[ vals$keeprows, , drop = FALSE]
exclude <- XYdata[!vals$keeprows, , drop = FALSE]
keep <- subset(keep, Concn > 0)
exclude <- subset(exclude, Concn > 0)
nls.fit <- nls(Values ~ (ymax* keep$Concn / (ec50 + keep$Concn)) + Ns*keep$Concn + ymin, data=keep,
start=list(ymax=max(keep$Values), ymin = min(keep$Values), ec50 = 3, Ns = 0.2045514))
keep$nls.pred <- fitted(nls.fit)
ggplot(keep, aes(y = Values,x = Concn))+geom_point(size = 5,colour="red")+
geom_smooth(method = "loess",fullrange = F, se = T, aes(Concn, nls.pred),size = 1.5,colour="blue1")+
geom_point(data = exclude, shape = 21, fill = NA, color = "black",size = 5, alpha = 0.7) +
xlab('Concentration (nM)')+ ylab('Units')+
scale_x_log10(labels=NonScientific)+ggtitle("Standard Curve")+theme_classic()+
theme(panel.background = element_rect(colour = "black", size=1),
plot.margin = margin(1, 3, 0.5, 1, "cm"),
plot.title = element_text(hjust = 0, face="bold",color="#993333", size=16),
axis.title = element_text(face="bold", color="#993333", size=14),
axis.text.x = element_text(face="bold", color="#666666", size=12),
axis.text.y = element_text(face="bold", color="#666666", size=12))
})
# Toggle points that are clicked
observeEvent(input$plot1_click, {
res <- nearPoints(XYdata, input$plot1_click, allRows = TRUE)
vals$keeprows <- xor(vals$keeprows, res$selected_)
})
# Toggle points that are brushed, when button is clicked
observeEvent(input$exclude_toggle, {
res <- brushedPoints(XYdata, input$plot1_brush, allRows = TRUE)
vals$keeprows <- xor(vals$keeprows, res$selected_)
})
# Reset all points
observeEvent(input$exclude_reset, {
vals$keeprows <- rep(TRUE, nrow(XYdata))
})
}
shinyApp(ui, server)
I tried replacing the plotting portion of the script with the following but I am not able to interactively plot. What am I doing wrong here?
plot(Values ~ Concn, keep, subset = Concn > 0, col = 4, cex = 2, log = "x")
title(main = "XY Std curve")
lines(predict(nls.fit, new = list(Concn = Concn)) ~ Concn, keep)
points(Values ~ Concn, exclude, subset = Concn > 0, col = 1, cex = 2, log = "x")
You have to add xvarand yvar parameters to nearPoints:
res <- nearPoints(XYdata, input$plot1_click, xvar="Concn", yvar="Values", allRows = TRUE)
The working code implementing #HubertL's suggestion for someone like me to use for interactive plotting and to knockout outliers by clicking on or by selecting the point(s) using mouse:
XYdata <- data.frame(cbind(Values = c(91.8, 95.3, 99.8, 123.3, 202.9, 619.8, 1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
Concn = c(1000, 300, 100,30, 10, 3, 1, 0.3, 0.1, 0.03, 0.01, 0)))
ui <- fluidPage(
fluidRow(
column(width = 6,
plotOutput("plot1", height = 350,click = "plot1_click", brush = brushOpts(id = "plot1_brush")),
actionButton("exclude_reset", "Reset")
)
)
)
server <- function(input, output) {
# For storing which rows have been excluded
vals <- reactiveValues(
keeprows = rep(TRUE, nrow(XYdata))
)
NonScientific <- function(l) {l <- format(l, scientific = FALSE); parse(text=l)}
output$plot1 <- renderPlot({
# Plot the kept and excluded points as two separate data sets
XYdata <- data.frame(cbind(Values = c(91.8, 95.3, 99.8, 123.3, 202.9, 619.8, 1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
Concn = c(1000, 300, 100, 30, 10, 3, 1, 0.3, 0.1, 0.03, 0.01, 0)))
keep <- XYdata[ vals$keeprows, , drop = FALSE]
exclude <- XYdata[!vals$keeprows, , drop = FALSE]
keep <- subset(keep, Concn > 0)
exclude <- subset(exclude, Concn > 0)
o <- order(keep$Concn)
keep <- keep[o, ]
fo <- Values ~ (ymax* Concn / (ec50 + Concn)) + Ns * Concn + ymin
st <- list(ymax=max(keep$Values), ymin = min(keep$Values), ec50 = 3, Ns = 0.2045514)
nls.fit <- nls(fo, data = keep, start = st)
plot(Values ~ Concn, keep, subset = Concn > 0, type = 'p',pch = 16,cex = 2, axes = FALSE, frame.plot = TRUE,log = "x")
title(main = "Interactive Std curve")
logRange <- with(keep, log(range(Concn[Concn > 0])))
x <- exp(seq(logRange[1], logRange[2], length = 250))
lines(x, predict(nls.fit, new = list(Concn = x)))
points(Values ~ Concn, exclude, subset = Concn > 0, col = 1, cex = 2)
my.at <- 10^(-2:3)
axis(1, at = my.at, labels = formatC(my.at, format = "fg"))
axis(2)
})
# Toggle points that are clicked
observeEvent(input$plot1_click, {
res <- nearPoints(XYdata, input$plot1_click, xvar="Concn", yvar="Values", allRows = TRUE)
vals$keeprows <- xor(vals$keeprows, res$selected_)
})
# Reset all points
observeEvent(input$exclude_reset, {
vals$keeprows <- rep(TRUE, nrow(XYdata))
})
}
shinyApp(ui, server)
I am trying to start using plotly with shiny, but unfortunately it doesn't work with my code. As an example I wrote this (sorry that descriptions in UI part are in russian):
UI:
library(shiny)
library(ggplot2)
library(plotly)
library(mvtnorm)
shinyUI(fluidPage(
titlePanel("Грачев Влад инкорпорейшн"),
sidebarLayout(
sidebarPanel(
sliderInput('n_obs', 'Количество испытаний', min = 0, max = 1000, value = 500, animate = TRUE),
sliderInput('prc', 'Средний рост детей', min = 170, max = 180, value = 175, step = 0.5, animate = TRUE),
sliderInput('prp', 'Средний рост родителей', min = 170, max = 180, value = 175, step = 0.5, animate = TRUE),
sliderInput('corr', 'Корреляция между ростом ребенка и ростом родителей', min = -1, max = 1, value = 0.5, step = 0.1, animate = TRUE),
sliderInput('stdc', 'Стандартное отклонение роста детей', min = 0, max = 1, value = 0.5, animate = TRUE),
sliderInput('stdp', 'Стандартное отклонение роста родителей', min = 0, max = 1, value = 0.5, animate = TRUE)
),
mainPanel(
plotOutput('dotplot'),
plotOutput('plotl')
)
)
))
Server:
shinyServer(function(input, output){
update_x <- reactive({
mu <- c(input$prc,input$prp)
A <-matrix(
c(input$stdc, input$corr*sqrt(input$stdc*input$stdp), input$corr*sqrt(input$stdc*input$stdp), input$stdp),
nrow = 2
)
X <- rmvnorm(input$n_obs, mean = mu, sigma = A)
X
})
output$dotplot <- renderPlot({
X <- data.frame(update_x())
g <- ggplot(X, aes(x=X[,1], y = X[,2])) + geom_jitter() + stat_smooth()
gg <- ggplotly(g)
gg
})
output$plotl <- renderPlotly({
X <- data.frame(update_x())
g <-ggplot(X, aes(X[,2])) + geom_histogram(binwidth = 0.2)
gg <- ggplotly(g)
gg
})
})
It works without plotly (just ordinary renderPlot and ggplot graph):
enter image description here
But when i am starting the code above it doesn't show any graphs or warnings (only empty space) and there are 2 warnings in the console: Using size for a discrete variable is not advised.
Thanks in advance
Vlad