How to hover over ggplot with transformed values in shiny - r

I want to display some of the data in tooltip when hovering on the plot in shiny. I have used this script, and the data is showing nicely when I use the variables as they are (p and min_p). However what I really need is to display a log-transformed p and min_p, so my ggplot would be the following:
ggplot(dataset, aes(x = -log10(p), y = -log10(min_p))) +
geom_point()
And that's the problem, because hover_info does not recognize the data anymore, and I get the following error:
Error: replacement table has 0 rows, replaced table has 20
I am not sure how this can be fixed, and I admit I don't fully understand how the hovering works.
Here is the code with a sample data:
library(shiny)
library(shinydashboard)
library(ggplot2)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Plot result", tabName = "scatterplot", icon = icon("area-chart"))
))
body <- dashboardBody(
tabItems(
tabItem(tabName = "scatterplot",
fluidRow(
box(
uiOutput("scatterPlotButton"),
width = 5
),
box(
title="PLOT",solidHeader = TRUE, status="primary",
plotOutput("plot",
hover = hoverOpts("plot_hover", delay = 100, delayType = "debounce")),
uiOutput("hover_info"),
width=9
)
)
)
)
)
ui=dashboardPage(
dashboardHeader(title = "analysis"),
sidebar,
body
)
server=shinyServer(function(input, output, session) {
dataset <- structure(list(p = c(6.03934743495282e-02, 1.50433174696588e-01,
2.08047037184403e-03, 5.89297106629446e-05, 0.000102485231497565,
0.0010651774924444, 0.0126458836222225, 0.000210364148948929,
0.00274720409905674, 0.281095738489031, 0.000316170681574214,
0.0316321461125659, 0.000369171267912158, 0.000369171267912158,
0.0395213746526263, 0.475174078010843, 0.000718770258398781,
0.760859052164441, 0.000810153915789446, 0.000875314011490406),
ratio_p_group_min = c(1.57380553778931, 1.11245772000324,
1.504084996599, 1.00963266560562, 1.28098052443163, 1.49882201127675,
1.10761702001084, 0.767267328293303, 1.03412495601202, 1.33508933929913,
0.835478202626155, 0.998537147454481, 1.2008830437325, 1.2008830437325,
1.15710746065582, 0.99677375722945, 1.37744067975694, 1.3666109673056,
1.34583027836758, 1.34766012381264),
min_p = c(0.15789, 0.25772, 0.56599, 0.99632, 0.00004, 0.00275, 0.10761,
0.76726, 0.00103, 0.00013, 0.83547, 0.99853, 0.00120, 0.12008,
0.01157, 0.99677, 0.01377, 0.13666, 0.14583, 0.01347),
genes = c("Gene1", "Gene2", "Gene3", "Gene4", "Gene5", "Gene6", "Gene7",
"Gene8", "Gene9", "Gene10", "Gene11", "Gene12", "Gene13", "Gene14",
"Gene15", "Gene16", "Gene17", "Gene18", "Gene19", "Gene20")),
.Names = c("p", "ratio_p_group_min","min_p","genes"),
row.names = c(NA, 20L), class = "data.frame")
output$scatterPlotButton <- renderUI({
actionButton("scatterPlotButton", "Generate Plot", class="btn-block btn-primary")
})
scatterPlot <- eventReactive(input$scatterPlotButton,{
if (is.null(input$scatterPlotButton)) return()
dataset <- dataset[which(round(dataset$ratio_p_group_min,digits=2)>=0 & round(-log10(dataset$p),digits=2)>=0 & !is.na(dataset$ratio_p_group_min)),]
dataset$ratio_p_group_min=ifelse(dataset$ratio_p_group_min>2 & dataset$p>0.05,1,dataset$ratio_p_group_min)
ggplot(dataset, aes(x = -log10(p), y = -log10(min_p))) +
geom_point()
})
output$plot <- renderPlot({ scatterPlot() })
output$hover_info <- renderUI({
if (is.null(input$scatterPlotButton)) return()
dataset <- dataset[which(round(dataset$ratio_p_group_min,digits=2)>=0 & round(-log10(dataset$p),digits=2)>=0 & !is.na(dataset$ratio_p_group_min)),]
hover <- input$plot_hover
point <- nearPoints(dataset, hover, threshold = 5, maxpoints = 1, addDist = TRUE)
if (nrow(point) == 0) return(NULL)
left_pct <- (hover$x - hover$domain$left) / (hover$domain$right - hover$domain$left)
top_pct <- (hover$domain$top - hover$y) / (hover$domain$top - hover$domain$bottom)
left_px <- hover$range$left + left_pct * (hover$range$right - hover$range$left)
top_px <- hover$range$top + top_pct * (hover$range$bottom - hover$range$top)
style <- paste0("position:absolute; z-index:100; background-color: rgba(245, 245, 245, 0.85); ",
"left:", left_px + 2, "px; top:", top_px + 2, "px;")
wellPanel(
style = style,
p(HTML(paste0(point)))
)
})
})
shinyApp(ui=ui, server=server)
UPDATE
I have found a not so elegant solution: create new variables in dataset for -log10(p) and -log10(min_p) and use these new variables in ggplot.
dataset$LogP = -log10(dataset$p)
dataset$LogMinP = -log10(dataset$min_p)
ggplot(dataset, aes(x = LogP, y = LogMinP)) +
geom_point()
But I am still wondering if this could have been avoided somehow.

You could also use the plotly package. Simply call ggploty() after your ggplot object.

Related

Shiny combining inputs

I have a data set with three laps (15s/lap) each of which shows the different speed for every second:
AA <- as.data.frame(cbind(c(10,12,11,12,12,11,12,13,11,9,9,12,11,10,12,9,8,7,9,8,7,9,9,8,9,7,9,10,10,10,7,6,7,8,8,7,6,6,7,8,7,6,7,8,8),
c(rep("Lap_1",15),rep("Lap_2",15),rep("Lap_3",15))))
I want to compare the three laps together, but for the first one I'd like to use a sliderInput to select only some of the 15 secondes. I'm having some difficulties to add that to my code. Here is what I have for the moment:
install.packages("shiny")
install.packages("ggplot2")
library(shiny)
library(ggplot2)
colnames(AA) <- c("Speed","Lap")
AA$Speed <- as.numeric(as.character(AA$Speed))
ui=shinyUI(
fluidPage(
titlePanel("Title here"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("lap_choose",
label = "Choose the laps",
choices = c("Lap_1","Lap_2","Lap_3")),
sliderInput("secs_1",
"Seconds in L1:",
min = 0,
max = 15,
value = c(3,10),
step=1)),
mainPanel(
plotOutput("Comparison"))
)
)
)
server=function(input,output){
#data manipulation
data_1=reactive({
return(AA[AA$Lap%in%input$lap_choose,])
})
output$Comparison <- renderPlot({
ggplot(data=data_1(), aes(Speed, fill = Lap)) +
stat_density(aes(y = ..density..),
position = "identity",
color = "black",
alpha = 0.8) +
xlab("Distribution") +
ylab("Density") +
ggtitle("Comparison") +
theme(plot.title = element_text(hjust = 0.5,size=24, face="bold"))
})
}
shinyApp(ui,server)
I should use the secs_1 at some point to update data_1, but didn't find out how yet. Any ideas?
If i am understanding correctly, you want to filter out some values(based on sec_1 sliderInput) if "lap" variable is "lap_1".
Try using ifelse statement in data_1 function.
data_1=reactive({
xc <- AA[AA$Lap%in%input$lap_choose,]
gh <- ifelse(xc$Lap == "Lap_1" & xc$Speed %in% c(input$secs_1[1],input$secs_1[2]),
FALSE, TRUE)
return(xc[gh,])
})

multiple selection in checkboxGroupInput and plotting in shiny

In my shiny app I have a checkboxGroupInput
How should I do the plot command in server function, in a way that I plot the TurbInt_mean against MeanWindSpeed_mean and add lines (curves) to the plot by user selection ?
I have tried to summaries my shiny app as reproduce-able code as follow (you have to first load the sample data that I have provided)
library(shiny)
ui <- fluidPage(
checkboxGroupInput("variable", "Select IEC Classes for TI",c("A Plus" = "ap","A" = "a","B" = "b","C"="c")),
plotOutput("plotmeanTI",width = "100%") )
server <- function(input, output, session){
output$plotmeanTI <- renderPlot({
plot(as.matrix(TI_plot[,1]),as.matrix(TI_plot[,2]),t='o',ylim=c(0,1),xaxs="i",
xlab="Mean Wind Speed", ylab="<TI>")
if(input$variable=="ap"){lines(as.matrix(TI_plot[,1]),TI_plot$NTM_A_Plus_mean,col=6)}
if(input$variable=="a"){lines(as.matrix(TI_plot[,1]),TI_plot$NTM_A_mean,col=2)}
if(input$variable=="b"){lines(as.matrix(TI_plot[,1]),TI_plot$NTM_B_mean,col=3)}
if(input$variable=="c"){lines(as.matrix(TI_plot[,1]),TI_plot$NTM_C_mean,col=4)}
})
}
shinyApp(ui=ui,server=server)
If user select 1, one curve should be added, if select more than one, I want to have multiple curves added to my plot.I can do it for single selection like I have explained in my code, but when I have multi selection it does not work.
My data set looks like :
dput(TI_plot)
structure(list(MeanWindSpeed_mean = c(0.292023070097604, 1.12011882699226,
2.0283906614786, 3.00947886508396, 4.01428066037736, 5.01250749719984,
6.0080377166157, 7.00777409860191, 8.0049941822883, 9.00201938353988,
9.99646762244478, 10.9883558855227, 11.9798700705476, 12.976996101646,
13.9653724394786, 14.9495068163593, 15.9628459343795, 16.9708685581934,
17.9623943661972, 18.992621231979, 19.9643220338983, 20.9834693877551,
22.0170278637771, 22.9658904109589, 24.0025266903915, 24.9935025380711
), TurbInt_mean = c(3.02705430346051, 0.420402191213343, 0.264195029831388,
0.215109260166585, 0.18794121258946, 0.16699392997796, 0.148261539245668,
0.134479958525654, 0.122038442146089, 0.110595865904036, 0.097103704211826,
0.0836329541372291, 0.0708397249149876, 0.0622491842333237, 0.0591184473929236,
0.0611678829190056, 0.0652080242510699, 0.0690131441806601, 0.073762588028169,
0.0756961992136304, 0.0805696610169492, 0.0817446428571429, 0.0830263157894737,
0.0827277397260274, 0.0749537366548043, 0.0765532994923858),
NTM_A_Plus_mean = c(Inf, 1.10260388189292, 0.642329939163608,
0.473065816856713, 0.387417559923049, 0.336769624752903,
0.303163441845455, 0.27908457313955, 0.261084722917897, 0.247090026094941,
0.235918715179959, 0.226796351934008, 0.219190019655214,
0.212713243118379, 0.20720881268079, 0.202452008587075, 0.19816685602934,
0.19441329542209, 0.191131377464549, 0.188086340606011, 0.185500707351721,
0.18304730715887, 0.180790073836667, 0.178898058874634, 0.177002145398197,
0.175335040729601), NTM_A_mean = c(Inf, 0.98009233946037,
0.570959945923208, 0.420502948317078, 0.344371164376044,
0.299350777558136, 0.269478614973738, 0.248075176124045,
0.232075309260353, 0.219635578751059, 0.209705524604408,
0.201596757274674, 0.194835573026857, 0.189078438327448,
0.184185611271814, 0.179957340966289, 0.176148316470525,
0.172811818152969, 0.169894557746266, 0.167187858316455,
0.164889517645975, 0.162708717474551, 0.160702287854815,
0.159020496777452, 0.157335240353953, 0.155853369537423),
NTM_B_mean = c(Inf, 0.857580797027824, 0.499589952682807,
0.367940079777444, 0.301324768829038, 0.261931930363369,
0.23579378810202, 0.217065779108539, 0.203065895602809, 0.192181131407176,
0.183492334028857, 0.176397162615339, 0.1704811263985, 0.165443633536517,
0.161162409862837, 0.157462673345503, 0.154129776911709,
0.151210340883848, 0.148657738027983, 0.146289376026898,
0.144278327940228, 0.142370127790232, 0.140614501872963,
0.139142934680271, 0.137668335309708, 0.136371698345246),
NTM_C_mean = c(Inf, 0.735069254595278, 0.428219959442406,
0.315377211237809, 0.258278373282033, 0.224513083168602,
0.202108961230303, 0.186056382093034, 0.174056481945265,
0.164726684063294, 0.157279143453306, 0.151197567956005,
0.146126679770143, 0.141808828745586, 0.13813920845386, 0.134968005724717,
0.132111237352894, 0.129608863614727, 0.127420918309699,
0.125390893737341, 0.123667138234481, 0.122031538105913,
0.120526715891111, 0.119265372583089, 0.118001430265464,
0.116890027153068)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -26L), .Names = c("MeanWindSpeed_mean",
"TurbInt_mean", "NTM_A_Plus_mean", "NTM_A_mean", "NTM_B_mean",
"NTM_C_mean"))
the head of TI_plot is like :
head(TI_plot)
# A tibble: 6 x 6
MeanWindSpeed_mean TurbInt_mean NTM_A_Plus_mean NTM_A_mean NTM_B_mean NTM_C_mean
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 0.2920231 3.0270543 Inf Inf Inf Inf
2 1.1201188 0.4204022 1.1026039 0.9800923 0.8575808 0.7350693
3 2.0283907 0.2641950 0.6423299 0.5709599 0.4995900 0.4282200
4 3.0094789 0.2151093 0.4730658 0.4205029 0.3679401 0.3153772
5 4.0142807 0.1879412 0.3874176 0.3443712 0.3013248 0.2582784
6 5.0125075 0.1669939 0.3367696 0.2993508 0.2619319 0.2245131
We could use switch
library(shiny)
ui <- fluidPage(
checkboxGroupInput("variable", "Select IEC Classes for TI",c("A Plus" = "ap","A" = "a","B" = "b","C"="c"),
selected = c("A Plus" = "ap")),
plotOutput("plotmeanTI",width = "100%")
)
server <- function(input, output, session){
output$plotmeanTI <- renderPlot({
f1 <- function(nm1){
switch(nm1,
ap = lines(TI_plot[[1]],TI_plot$NTM_A_Plus_mean,col=6),
a = lines(TI_plot[[1]],TI_plot$NTM_A_mean,col=2),
b = lines(TI_plot[[1]],TI_plot$NTM_B_mean,col=3),
c = lines(TI_plot[[1]],TI_plot$NTM_C_mean,col=4)
)
}
if(is.null(input$variable)) {
plot(TI_plot[[1]], TI_plot[[2]],t='o',ylim=c(0,1),xaxs="i",
xlab="Mean Wind Speed", ylab="<TI>")
} else {
plot(TI_plot[[1]], TI_plot[[2]],t='o',ylim=c(0,1),xaxs="i",
xlab="Mean Wind Speed", ylab="<TI>")
f1(input$variable)
}
})
}
shinyApp(ui=ui,server=server)
-output
Using ggplot2
library(shiny)
library(ggplot2)
library(tidyr)
library(dplyr)
ui <- fluidPage(
checkboxGroupInput("variable", "Select IEC Classes for TI",c("A Plus" = "ap","A" = "a","B" = "b","C"="c"),
selected = c("A Plus" = "ap")),
plotOutput("plotmeanTI",width = "100%") )
server <- function(input, output, session){
output$plotmeanTI <- renderPlot({
keyvaldata <- data.frame(key = c('NTM_A_Plus_mean', 'NTM_A_mean', 'NTM_B_mean', 'NTM_C_mean' ),
Var = c('ap', 'a', 'b', 'c'), stringsAsFactors = FALSE)
p1 <- gather(TI_plot, key, val, -MeanWindSpeed_mean, -TurbInt_mean) %>%
left_join(., keyvaldata) %>%
filter(Var %in% input$variable) %>%
ggplot(., aes(MeanWindSpeed_mean, TurbInt_mean, colour = Var)) +
geom_line() +
geom_line(aes(y =val)) +
labs(x = "Mean Wind Speed", y = "<TI>") +
theme_bw()
if(is.null(input$variable)) {
ggplot(TI_plot, aes(MeanWindSpeed_mean, TurbInt_mean)) +
geom_line() +
labs(x = "Mean Wind Speed", y = "<TI>") +
theme_bw()
} else {
p1
}
})
}
shinyApp(ui=ui,server=server)
-output

How can I use for loop inside shiny server?

This is my very first question here, can anybody help me to solve this problem? I will really appreciate that!
I am trying to create a vector based on existing vectors. But the for loop inside shiny server didn't work for me. I have tried many ways but still cannot make it.
ui <- (
tabPanel(
"Momentum Analysis",
sidebarPanel(
width = 4,
textInput("ticker2", "Stock ticker:"),
dateRangeInput(
"date2",
"Date Range:",
max = Sys.Date(),
end = Sys.Date(),
startview = "year"
),
numericInput(
"alpha",
"Volatility smoothing parameter:",
min = 0,
max = 1,
value = 0.05
),
numericInput(
"beta",
"Momentum smoothing parameter:",
min = 0,
max = 1,
value = 0.05
),
radioButtons("type2",
"Chart Type:",
c(
"Momentum vs. Volatility" = "mvv",
"Signal to Noise Ratio" = "snr"
)),
actionButton(
"plot2",
"Plot",
icon("line-chart"),
style = "color: #fff;
background-color: #337ab7;
border-color: #2e6da4"
),
div(
style = "display: inline-block;
vertical-align: top",
downloadButton("download2", "Download historical stock price data")
)
),
mainPanel(plotOutput("chart2"))
)
)
)
server <- function(input, output){
stock2 <-
reactive(
getSymbols(
toupper(input$ticker2),
from = as.Date(input$date2[1]) - 150,
to = input$date2[2],
src = "google",
auto.assign = F
)
)
stock3 <- reactive(as.data.table(stock2()))
stock <- reactive(as.data.frame(stock3()))
stock.return <- reactive(diff(log(stock()[, 5])))
stock.mu <- reactive(mean(stock.return()))
stock.var <- reactive((stock.return() - stock.mu()) ^ 2)
stock.var.smoothed <- reactive(rep(0, length(stock.return())))
stock.var.smoothed <- reactive({
for (i in 2:length(stock.var())) {
stock.var.smoothed[1] <- stock.var()[1]
stock.var.smoothed[i] <-
(1 - input$alpha) * stock.var.smoothed()[i - 1] + input$alpha * stock.var()[i]
}
})
stock.std.smoothed <- reactive(sqrt(stock.var.smoothed()))
stock.std.smoothed.annually <- reactive(stock.var.smoothed() * sqrt(252))
stock.momentum <- reactive(stock.return())
stock.momentum.smoothed <- reactive(rep(0, length(stock.return())))
stock.momentum.smoothed <- reactive({
for (i in 2:length(stock.return())) {
stock.momentum.smoothed[1] <- stock.momentum()[1]
stock.momentum.smoothed[i] <-
(1 - input$beta) * stock.momentum.smoothed()[i - 1] + input$beta * stock.return()[i]
}
})
stock.momentum.smoothed.annually <-
reactive(stock.momentum.smoothed() * 252 / 100)
stock.SNR <-
reactive(stock.momentum.smoothed.annually() / stock.std.smoothed.annually())
output$chart2 <- renderPlot({
req(input$plot2)
if (input$type2 == "mvv"){
plot(
stock.momentum.smoothed(),
main = "Momentum v.s. Volatility",
col = "red",
type = "l",
xaxt = "n",
ylab = "Momentum v.s. Volatility",
xlab = "Date",
ylim = c(-2, 2)
)
lines(stock.std.smoothed())
axis(1, at = 1:length(stock()[, 1]), labels = stock()[, 1])
}
else if (input$type2 == "snr"){
plot(
stock.SNR(),
main = "Signal to Noise",
type = "l",
col = "red",
ylim = c(-1, 1),
xaxt = "n",
ylab = "Signal to Noise Ratio",
xlab = "Date"
)
abline(h = 0.5)
axis(1, at = 1:length(stock()[, 1]), labels = stock()[, 1])
}
})
output$download2 <- downloadHandler(
filename = function() {
paste(toupper(input$ticker2),
" ",
input$date2[1],
" ",
input$date2[2],
".xlsx",
sep = "")
},
content = function(file) {
write.xlsx2(stock2()[paste0(input$date2, "/"),], file)
}
)
}
I am trying to plot the stock's momentum vs volatility, both are smoothed. My app has some other tabs but they are irrelevant so I just hided the code.
The only problem here is the loop and the reactive function. Thank you!
Please refer to Konrad Rudolph's answer
For loop inside reactive function in Shiny
I was trying to assign a vector with a function (reactive). But I didn't give any return to that function and so that I cannot call this function.

R Shiny: How do I use nearPoints on a geom_area or stacked geom_bar?

I'm trying to use hover tooltips on a geom_area, but I can't get them to work with that geometry. It only displays lowest set of grouped variables (in the example below, it will show 'Lakers' hover values, but not 'Celtics'.
Interestingly, if you replace the geom_area with, for example, geom_point, the code below works fine. But for the real dashboard I'm making, an area chart is necessary.
library("shiny")
library("ggplot2")
d <- data.frame(date = as.Date(c("2017-01-01", "2017-01-02", "2017-01-03",
"2017-01-01", "2017-01-02", "2017-01-03")),
team = c("Celtics", "Celtics", "Celtics",
"Lakers", "Lakers", "Lakers"),
points_scored = c(108, 89, 95, 78, 93, 82))
ui <- fluidPage(
mainPanel(
plotOutput("graph",
hover = hoverOpts("plot_hover", delay = 100, delayType = "debounce")),
uiOutput("hover_info")
)
)
server <- function(input, output) {
output$graph <- renderPlot({
ggplot(d, aes(x = date, y = points_scored, fill = team)) +
geom_area()
})
output$hover_info <- renderUI({
hover <- input$plot_hover
point <- nearPoints(d, hover, threshold = 5, maxpoints = 1, addDist = TRUE)
if (nrow(point) == 0) return(NULL)
wellPanel(
paste0(point$team, " - ", point$date, ": ", point$points_scored)
)
})
}
runApp(list(ui = ui, server = server))
Thanks in advance!
--- Edit ---
It's actually displaying the hover in the incorrect location. See the attached picture. It treats the point (Celtics on Jan 1) as if it's still at y = 108. I want it to hover at the top of the visible red bar (108 + 78 = 186), but still display 108.
I've found a sketchy workaround, but it makes the app do what I want it to do. My edited app only edits the server function, and goes something like this:
Continue to use the main dataframe 'd' to generate the graph. Continue to use the hover in plotOutput off of that graph
Create a workaround dataframe 'd_workaround' that is identical, except it contains 1) the actual y position of the points in a column with the same name as the y column in 'd' and the graph (points_scored. I wanted to name this 'position', but the app only worked if it had the same name as the y column in 'd') and 2) the 'real' value that I want my tooltip to display (points_scored_real)
Direct my nearPoints() to use d_workaround, and my tooltips to display points_scored_real from that column
The app looks like this:
library(shiny)
library(ggplot2)
library(dplyr)
library(tidyr)
library(stringr)
d <- data.frame(date = as.Date(c("2017-01-01", "2017-01-02", "2017-01-03",
"2017-01-01", "2017-01-02", "2017-01-03")),
team = c("Celtics", "Celtics", "Celtics",
"Lakers", "Lakers", "Lakers"),
points_scored = c(108, 89, 95, 78, 93, 82))
ui <- fluidPage(
mainPanel(
plotOutput("graph",
hover = hoverOpts("plot_hover", delay = 100, delayType = "debounce")),
uiOutput("hover_info")
)
)
server <- function(input, output) {
output$graph <- renderPlot({
ggplot(d, aes(x = date, y = points_scored, fill = team)) +
geom_area()
})
output$hover_info <- renderUI({
d_workaround <- d %>%
spread(team, points_scored) %>%
mutate(Celtics = str_c(Celtics + Lakers, "-", Celtics),
Lakers = str_c(Lakers, "-", Lakers)) %>%
gather(team, points_scored, Celtics, Lakers) %>%
separate(points_scored, c("points_scored", "points_scored_real"), convert = TRUE)
hover <- input$plot_hover
point <- nearPoints(d_workaround, hover, threshold = 10, maxpoints = 1, addDist = TRUE)
if (nrow(point) == 0) return(NULL)
wellPanel(
paste0(point$team, " - ", point$date, ": ", point$points_scored_real)
)
})
}
runApp(list(ui = ui, server = server))

R Shiny: Tooltip in ggplot

I want the values of the height or weight to show when I hover over a point in the graph. I already tried to make this work by using the plotly package and the example of this link. But I got all kind of errors and I do not know how to make it work.
I've included my whole code so I hope someone can help me with this problem.
library("shiny")
library("ggplot2")
library('readxl')
library('gridExtra')
ui<- fluidPage(
titlePanel("Animals"),
sidebarLayout(
sidebarPanel(
helpText("Create graph of height and/or weight animals"),
selectInput("location",
label = "Choose a location",
choices = list("New York"="New York", "Philadelphia" = "Philadelphia"),
selected = "New York"),
uiOutput("animal"),
checkboxGroupInput("opti",
label = "Option",
choices = c("weight", "height"),
selected = "weight")
),
mainPanel(plotOutput("graph"))
))
server <- function(input, output){
animal <- read_excel('data/animals.xlsx', sheet =1)
var <- reactive({
switch(input$location,
"New York" = list("Cat1", "Dog2"),
"Philadelphia"= list("Cat4","Dog3"))
})
output$animal <- renderUI({
checkboxGroupInput("anim", "Choose an animal",
var())
})
output$graph <- renderPlot({
if (length(input$anim)==1){
p <- ggplot(subset(animal, Name %in% input$anim & Location %in% input$location), aes(x=date))
if ("weight" %in% input$opti){
p <- p + geom_line(aes(y=weight)) + geom_point(aes(y=weight))
}
if ("height" %in% input$opti){
p <- p + geom_line(aes(y=height)) + geom_point(aes(y=height))
}
print(p)
}
if (length(input$anim)==2){
p1 <- ggplot(subset(animal, Name %in% input$anim[1] & Location %in% input$location), aes(x=date))
p2 <- ggplot(subset(animal, Name %in% input$anim[2] & Location %in% input$location), aes(x=date))
if ("weight" %in% input$opti){
p1 <- p1 + geom_line(aes(y=weight)) + geom_point(aes(y=weight))
p2 <- p2 + geom_line(aes(y=weight)) + geom_point(aes(y=weight))
}
if ("height" %in% input$opti){
p1 <- p1 + geom_line(aes(y=height)) + geom_point(aes(y=height))
p2 <- p2 + geom_line(aes(y=height)) + geom_point(aes(y=height))
}
grid.arrange(p1,p2, ncol = 2)
}
})
}
shinyApp(ui=ui, server= server)
A part of the data:
Location Name date weight height
New York Cat1 Mar-16 34,20 22,50
New York Cat1 Apr-16 35,02 23,02
New York Cat1 May-16 35,86 23,55
New York Cat1 Jun-16 36,72 24,09
New York Dog2 Mar-16 33,55 22,96
New York Dog2 Apr-16 33,62 23,42
New York Dog2 May-16 33,68 23,89
New York Dog2 Jun-16 33,75 24,37
Philadelphia Cat4 Mar-16 20,33 16,87
I used this tooltip and customised it a little bit.
Your plots initially don't show up because you don't return any plot. I return an ggplot object p without calling print function.
In general, I heavily modified your code and this is the result:
As the function nearPoints needs the same dataset that you pass to ggplot, I had to create a new reactive, in which I did some subsetting and reshaping of your data.
Instead of grid.arrange to create two seperate plots I used facet_grid (and hence I had to transform the data). I also used colours to differentiate lines.
Everything works fine with the example data you provided.
Full example:
rm(ui)
rm(server)
library("shiny")
library("ggplot2")
library('readxl')
library('gridExtra')
library(reshape) # for "melt"
ui<- fluidPage(
titlePanel("Animals"),
sidebarLayout(
sidebarPanel(
helpText("Create graph of height and/or weight animals"),
selectInput("location",
label = "Choose a location",
choices = list("New York"="New York", "Philadelphia" = "Philadelphia"),
selected = "New York"),
uiOutput("animal"),
checkboxGroupInput("opti",
label = "Option",
choices = c("weight", "height"),
selected = "weight")
),
mainPanel(
# this is an extra div used ONLY to create positioned ancestor for tooltip
# we don't change its position
div(
style = "position:relative",
plotOutput("graph",
hover = hoverOpts("plot_hover", delay = 100, delayType = "debounce")),
uiOutput("hover_info")
)
)
))
server <- function(input, output){
animal <- read_excel('data/animals.xlsx', sheet =1)
#animal <- read_excel("~/Downloads/test2.xlsx")
var <- reactive({
switch(input$location,
"New York" = c("Cat1", "Dog2"),
"Philadelphia"= c("Cat4","Dog3"))
})
output$animal <- renderUI({
checkboxGroupInput("anim", "Choose an animal",
var())
})
output$graph <- renderPlot({
req(input$anim, sub())
if (length(input$anim) == 1) {
p <- ggplot(sub(), aes(x = date, colour = variable))
p <- p + geom_line(aes(y = value)) +
geom_point(aes(y = value)) +
guides(colour = guide_legend(title = NULL))
return(p) # you have to return the plot
}
if (length(input$anim) == 2) {
p <- ggplot(sub(), aes(x = date, colour = variable)) +
geom_line(aes(y = value)) +
geom_point(aes(y = value)) +
facet_grid(~ Name) +
guides(colour = guide_legend(title = NULL))
return(p) # you have to return the plot
}
})
observe({
print(sub())
})
sub <- reactive({
req(input$anim)
if (length(input$anim) == 1) {
df <- animal[animal$Name %in% input$anim & animal$Location %in% input$location, ]
df <- melt(as.data.frame(df), measure.vars = c("weight", "height"))
df <- subset(df, df$variable %in% input$opti)
return(df)
}
if (length(input$anim) == 2) {
df <- animal[animal$Name %in% input$anim & animal$Location %in% input$location, ]
df$Name <- factor(df$Name)
df <- melt(as.data.frame(df), measure.vars = c("weight", "height"))
df <- subset(df, df$variable %in% input$opti)
return(df)
}
})
output$hover_info <- renderUI({
hover <- input$plot_hover
point <- nearPoints(sub(), hover, threshold = 5, maxpoints = 1, addDist = TRUE)
if (nrow(point) == 0) return(NULL)
left_pct <- (hover$x - hover$domain$left) / (hover$domain$right - hover$domain$left)
top_pct <- (hover$domain$top - hover$y) / (hover$domain$top - hover$domain$bottom)
left_px <- hover$range$left + left_pct * (hover$range$right - hover$range$left)
top_px <- hover$range$top + top_pct * (hover$range$bottom - hover$range$top)
style <- paste0("position:absolute; z-index:100; background-color: rgba(245, 245, 245, 0.85); ",
"left:", left_px + 2, "px; top:", top_px + 2, "px;")
wellPanel(
style = style,
p(HTML(paste0("<b>", point$variable, ": </b>", point$value)))
)
})
}
shinyApp(ui = ui, server = server)

Resources