Related
I have used bargap to decrease the width of bars in plotly but I want to bring themcloser whild keeping this width and not make them thicker.
library(tidyr)
library(stringr)
library(forcats)
library(plotly)
# data
Category<-c("First dose","Full vaccination")
`Uptake first dose`<-c(19.8,0)
`Uptake full vaccination`<-c(0,7.6)
`Not vaccinated`<-c(80.2,92.4)
ch5<-data.frame(Category,`Uptake first dose`,`Uptake full vaccination`,`Not vaccinated`)
# transform data
data.long <- ch5 %>%
pivot_longer(cols = -Category,
names_to = "vac",
values_to = "percent") %>%
mutate(vac = str_replace_all(vac, "\\.", " "),
vac = fct_rev(factor(vac)))
library(plotly)
plot_ly(data.long) %>%
add_bars(y = ~Category,
x = ~percent,
color = ~vac,
text = ~vac,
colors = c("#458d35", "#63bb47", "#e6e7e8"),
hovertemplate = paste('<b>%{y}</b>',
'<br>%{text}: %{x} ',
'<extra></extra>')) %>%
layout(font = list(color = '#a2a2a2'),barmode = "stack",
bargap = 0.7,
yaxis = list(fixedrange = TRUE,autorange="reversed",
title = "",
showticklabels = FALSE,
showgrid = FALSE,
showline = FALSE,
zeroline = FALSE),
xaxis = list(fixedrange = TRUE,title = "",ticksuffix = '%',
zeroline = FALSE,
showgrid = FALSE),
hoverlabel = list(bgcolor = "black",
bordercolor = "black",
font = list(color = "white")),
shapes = list(type = "line",
y0 = 0, y1 = 1, yref = "paper",
x0 = 70, x1 = 70),
annotations = list(text = "Target (70%)",
showarrow = FALSE,
x = 70,
y = 1.05,
yref = "paper"),
legend = list(orientation = 'h'))
I am trying to add custom button to update the y axis, here is a small example that is similar.
When I click on “frq” or “count” the correct bar chart appears, but the values are wrong (its take only one value for each city and put it in all gender categories bars)
library(plotly)
library(dplyr)
library(tidyr)
Occupation = c("Tel Aviv", "Paris", "Amsterdam", "Kyoto")
Gender = c("F", "M", "[missing]")
df <- crossing(Occupation, Gender) %>%
mutate(n = row_number()) %>%
group_by(.data[["Occupation"]]) %>%
mutate(frq = round(100 * (n / sum(n)), 1))
chart_type <- list(
type = "buttons",
direction = "right",
xanchor = 'center',
yanchor = "top",
pad = list('r' = 0, 't' = 10, 'b' = 10),
x = 0.1,
y = 1.20,
buttons = list(
list(
method = "update",
args = list(list(y = list(df$n))),
label = "count"
),
list(
method = "update",
args = list(list(y = list(df$frq))),
label = "frq"
)
)
)
df %>%
plot_ly(
x = ~ Occupation,
y = ~ n,
color = ~ Gender,
text = ~ n,
textposition = 'auto',
type = "bar"
) %>%
layout(updatemenus = list(chart_type))
Another version:
chart_type <- list(
type = "buttons",
direction = "right",
xanchor = 'center',
yanchor = "top",
pad = list('r'= 0, 't'= 10, 'b' = 10),
x = 0.1,
y = 1.20,
buttons = list(
list(method = "update",
args = list(list(visible = c(TRUE, FALSE)
)),
label = "count"),
list(method = "update",
args = list(list(visible = c(FALSE, TRUE)
)),
label = "frq")
))
df %>%
plot_ly(mode = 'markers',type = "bar") %>%
add_trace(x = ~Occupation, y = ~n, color = ~Gender,
text=~n, textposition = 'auto', visible = FALSE,
colorbar = list()) %>%
add_trace(x = ~Occupation, y = ~frq, color = ~Gender,
text=~frq, textposition = 'auto', visible = TRUE,
colorbar = list()) %>%
layout(updatemenus = list(chart_type))
After the click:
Could someone help me to implement this excellent jsfiddle in a "shiny" application with the highcharter package ?
https://jsfiddle.net/BlackLabel/nr1y47a9/
I started writing something like this but there are still some problems ...
Here's the result : https://pasteboard.co/J7qWN7v.png
library(highcharter)
library(httr)
library(dplyr)
getContent <- function(url) {
content(GET(url))
}
world <- getContent("https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/world-population.json")
mapdata <- get_data_from_map(download_map_data("custom/world"))
hcmap("custom/world", showInLegend = FALSE) %>%
hc_add_series(name = "Countries", color = '#E0E0E0') %>%
hc_add_series(data= world,type = "mapbubble", name = "Population", joinBy = c("iso-a3", "code3"), color= '#E0E0E0',
minSize = 4, maxSize = "12%",
tooltip = list(pointFormat = '{point.properties.hc-a2}: {point.z} thousands')) %>%
hc_colorAxis(
dataClasses = color_classes(c(0, 50000, 100000, 500000),
colors = c("green","#81c784","#43a047","#1b5e20")#,
# names = c("sg","tf","qsd")
)) %>%
hc_legend(title = list(text = "Mon titre"),
bubbleLegend = list(
enabled = TRUE,
borderColor = '#000000',
borderWidth = 3,
color = '#8bbc21',
connectorColor = '#000000'
),
align = "bottom", layout = "horizontal",
verticalAlign = "bottom",
floating = TRUE ,valueDecimals = 0,
symbolHeight = 11, symbolWidth = 11, symbolRadius = 0,
backgroundColor='#E0E0E8') %>%
hc_mapNavigation(enabled = TRUE) %>%
hc_exporting(enabled = TRUE)
Many thanks in advance !
Here's where I am, only the bubbleLegend (in comments #) doesn't work (it is displayed 3 times on the map)
mydf <- data.frame(
lat = c(-7.1871, 36.95733, 17.9356, -20.4379, 30.2496, -54.9593,
18.0365, 17.9688, 18, 18.005, 17.9538),
lon = c(129.3989, -121.576, -66.6961, -68.773, 138.6162, -128.3548,
-66.8143, -66.9705, -66.7603, -66.7765, -66.8265),
z = c(4.5, 2.77, 4.1, 5.2, 4.5, 5.1, 2.52, 3.7, 2.68, 2.71, 2.88),
part = c(10,15,8,20,30,12,5,17,21,9,11)
)
mydf <- mydf %>%
mutate(color = case_when(
part < 10 ~ "red",
part < 20 ~ "green",
TRUE ~ "blue"
))
hcmap() %>%
hc_add_series(data = mydf, type = "mapbubble", name = "EarthQuake", maxSize = '12%') %>%
hc_tooltip(useHTML = T,headerFormat='',pointFormat = paste('Location :{point.place}<br> Part: {point.part} <br> Magnitude : {point.z}')) %>%
hc_legend(enabled = TRUE,
title = list(text = "Mon titre"),
# bubbleLegend = list(
# enabled = TRUE,
# borderColor = '#000000',
# borderWidth = 3,
# color = '#8bbc21',
# connectorColor = '#000000'
# ),
align = "bottom", layout = "horizontal",
floating = TRUE ,valueDecimals = 0,
symbolHeight = 11, symbolWidth = 11, symbolRadius = 0) %>%
hc_colorAxis(
dataClasses = color_classes(breaks = c(0, 10, 20, 100),
colors = c("red","green","blue")
)) %>%
hc_title(text = "Global Seismic Activity") %>%
hc_mapNavigation(enabled = T)%>%
hc_exporting(enabled = TRUE)
Rather an easy solution but this bug is no longer present in the development version of highcharter.
Try
remotes::install_github("jbkunst/highcharter")
In the demo app below, the user can change the Selected state of the data rows by either clicking input$Go1 or select a region in the plot.
Selection the region in the plot is my intended functionality.
However, for a reason I fail to understand, the button does cause a re-render of the plot while select does not, even though both approaches have the same effect, i.e. a change in the values in column Selected of data.table RFImp_FP1
Why is it not working when I select points in the plot?
ui <- fluidPage(
actionButton(inputId = 'Go', label = 'Go'),
actionButton(inputId = 'Go2', label = 'Go2'),
plotlyOutput('RFAcc_FP1', width = 450)
)
server <- function(input, output, session) {
values <- reactiveValues()
observeEvent(input$Go, {
values$RFImp_FP1 <- data.table(MeanDecreaseAccuracy = runif(10, min = 0, max = 1), Variables = letters[1:10])
values$RFImp_FP1$Selected <- 1
})
observeEvent(input$Go2,{
values$RFImp_FP1$Selected[1:4] <- 1-values$RFImp_FP1$Selected[1:4]
print(values$RFImp_FP1$Selected)
})
observe({
if(!is.null(values$RFImp_FP1)) {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
data_df <- values$RFImp_FP1
data_df <- data_df %>% .[, Selected := if_else(Variables %in% parsToChange, 1-Selected, Selected)]
values$RFImp_FP1$Selected <- data_df$Selected
print(values$RFImp_FP1)
}
}
})
observeEvent(values$RFImp_FP1, {
print('seeing change')
})
output$RFAcc_FP1 <- renderPlotly({
values$RFImp_FP1
if(!is.null(values$RFImp_FP1)) {
RFImp_score <- values$RFImp_FP1[order(MeanDecreaseAccuracy)]
plotheight <- length(RFImp_score$Variables) * input$testme
p <- plot_ly(data = RFImp_score,
source = 'RFAcc_FP1',
height = plotheight,
width = 450) %>%
add_trace(x = RFImp_score$MeanDecreaseAccuracy,
y = RFImp_score$Variables,
type = 'scatter',
mode = 'markers',
color = factor(RFImp_score$Selected),
colors = c('#1b73c1', '#797979'),
symbol = factor(RFImp_score$Selected),
symbols = c('circle','x'),
marker = list(size = 6),
hoverinfo = "text",
text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
'<br>', 'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
sep = '')) %>%
layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
xaxis = list(title = 'Mean decrease accuracy index (%)',
tickformat = "%",
showgrid = F,
showline = T,
zeroline = F,
nticks = 5,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
yaxis = list(categoryarray = RFImp_score$Variables,
autorange = T,
showgrid = F,
showline = T,
autotick = T,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
dragmode = "select"
) %>% add_annotations(x = 0.5,
y = 1.05,
textangle = 0,
font = list(size = 14,
color = 'black'),
text = "Contribution to accuracy",
showarrow = F,
xref='paper',
yref='paper')
p$elementId <- NULL ## to surpress warning of widgetid
p <- p %>% config(displayModeBar = F)
p
} else {
p <- plot_ly( type = 'scatter', mode = 'markers', height = '400px', width = 450) %>% layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
xaxis = list(title = 'Mean decrease accuracy index', range= c(0,1), nticks = 2, showline = TRUE),
yaxis = list(title = 'Model input variables', range = c(0,1), nticks = 2, showline = TRUE)) %>%
add_annotations(x = 0.5, y = 1.1, textangle = 0, font = list(size = 14, color = 'black'),
text = 'Contribution to accuracy',
showarrow = F, xref='paper', yref='paper')
p$elementId <- NULL
p <- p %>% config(displayModeBar = F)
p}
})
}
shinyApp(ui, server)
select vs button result:
Don't ask me why, but I managed to get it to work with observeEvent and assigning NULL to the values$RFImp_FP1 before reassigning the altered data.table to it
values$RFImp_FP1 <- NULL
values$RFImp_FP1<- resDF
Full version:
library(shiny)
library(plotly)
library(dplyr)
library(data.table)
testDF <- data.table( MeanDecreaseAccuracy = runif(10, min = 0, max = 1), Variables = letters[1:10])
testDF$Selected <- T
ui <- fluidPage(
plotlyOutput('RFAcc_FP1', width = 450)
)
server <- function(input, output, session) {
values <- reactiveValues(RFImp_FP1 = testDF)
observeEvent(event_data("plotly_selected", source = 'RFAcc_FP1')$y, {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
resDF <- values$RFImp_FP1 %>% .[, Selected := if_else(Variables %in% parsToChange, !Selected, Selected)]
values$RFImp_FP1 <- NULL ## without this line the plot does not react
values$RFImp_FP1<- resDF ## re-assign the altered data.table to the reactiveValue
})
output$RFAcc_FP1 <- renderPlotly({
RFImp_score <- values$RFImp_FP1[order(MeanDecreaseAccuracy)]
plotheight <- length(RFImp_score$Variables) * 80
p <- plot_ly(data = RFImp_score,
source = 'RFAcc_FP1',
height = plotheight,
width = 450) %>%
add_trace(x = RFImp_score$MeanDecreaseAccuracy,
y = RFImp_score$Variables,
type = 'scatter',
mode = 'markers',
color = factor(RFImp_score$Selected),
colors = c('#F0F0F0', '#1b73c1'),
symbol = factor(RFImp_score$Selected),
symbols = c('x', 'circle'),
marker = list(size = 6),
hoverinfo = "text",
text = ~paste ('<br>', 'Parameter: ', RFImp_score$Variables,
'<br>', 'Mean decrease accuracy: ', format(round(RFImp_score$MeanDecreaseAccuracy*100, digits = 2), nsmall = 2),'%',
sep = '')) %>%
layout(
margin = list(l = 160, r= 20, b = 70, t = 50),
hoverlabel = list(font=list( color = '#1b73c1'), bgcolor='#f7fbff'),
xaxis = list(title = 'Mean decrease accuracy index (%)',
tickformat = "%",
showgrid = F,
showline = T,
zeroline = F,
nticks = 5,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
yaxis = list(categoryarray = RFImp_score$Variables,
autorange = T,
showgrid = F,
showline = T,
autotick = T,
font = list(size = 8),
ticks = "outside",
ticklen = 5,
tickwidth = 2,
tickcolor = toRGB("black")
),
dragmode = "select"
) %>% add_annotations(x = 0.5,
y = 1.05,
textangle = 0,
font = list(size = 14,
color = 'black'),
text = "Contribution to accuracy",
showarrow = F,
xref='paper',
yref='paper')
p <- p %>% config(displayModeBar = F)
p
})
}
shinyApp(ui, server)
and to avoid the plotly warnings about not being registered, we can change the observe structure to
observe({
if(!is.null( values$RFImp_FP1)) {
values$Selected <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
}
})
observeEvent(values$Selected, {
parsToChange <- event_data("plotly_selected", source = 'RFAcc_FP1')$y
if(!is.null(event_data("plotly_selected", source = 'RFAcc_FP1'))){
data_df <- values$RFImp_FP1
data_df <- data_df %>% .[, Selected := if_else(Variables %in% parsToChange, !Selected, Selected)]
values$RFImp_FP1 <- NULL
values$RFImp_FP1 <- data_df
}
})
One problem remains: making the same selection twice in a row does not trigger the observers as the selection is identical....
I am trying to plot waterfall chart with the following code. The only issue I am facing currently is the data marker which is not at the correct place. I want the data marker to be just below the end of each bar.
source('./r_files/flatten_HTML.r')
library("plotly")
dataset <- data.frame(Category = c("Akash Jain","Ankit Jain","Pankaj Jain","Nitin Pandey","Gopal Pandit","Ramnath Agarwal"),
TH = c(-62,-71,-1010,44,-44,200))
#dataset <- data.frame(Category = Values$Category, TH = Values$TH)
#dataset <- as.data.frame(cbind(Values$Category,Values$TH))
dataset$Category = dataset$Category
dataset$TH = dataset$TH
dataset$SortedCategoryLabel <- sapply(dataset$Category, function(x) gsub(" ", " <br> ", x))
dataset$SortedCategory <- factor(dataset$SortedCategoryLabel, levels = dataset$SortedCategoryLabel)
dataset$id <- seq_along(dataset$TH)
dataset$type <- ifelse(dataset$TH > 0, "in", "out")
dataset$type <- factor(dataset$type, levels = c("out", "in"))
dataset$end <- cumsum(dataset$TH)
dataset$start <- c(0, head(dataset$end, -1))
Hover_Text <- paste(dataset$Category, "= ", dataset$TH, "<br>")
dataset$colors <- ifelse(dataset$type =="out","red","green")
g <- plot_ly(dataset, x = ~SortedCategory, y = ~start, type = 'bar', marker = list(color = 'rgba(1,1,1, 0.0)'), hoverinfo = 'text') %>%
add_trace(y = dataset$TH , marker = list(color = ~colors), hoverinfo = "text", text = Hover_Text ) %>%
layout(title = '',
xaxis = list(title = ""),
yaxis = list(title = ""),
barmode = 'stack',
margin = list(l = 50, r = 30, b = 50, t = 20),
showlegend = FALSE) %>%
add_annotations(text = dataset$TH,
x = dataset$SortedCategoryLabel,
y = dataset$end,
xref = "dataset$SortedCategoryLabel",
yref = "dataset$end",
font = list(family = 'Arial',
size = 14,
color = "black"),
showarrow = FALSE)
g
Attached the screenshot of the waterfall chart.
So for the first bar, I need the data marker to be just below the end of red bar. Currently it is overlapping with the bar. And similarly for others.
Any help would be really appreciated.
Regards,
Akash
You should specify valign and height inside add_annotations:
vert.align <- c("bottom","top")[as.numeric(dataset$TH>0)+1]
g <- plot_ly(dataset, x = ~SortedCategory, y = ~start, type = 'bar',
marker = list(color = 'rgba(1,1,1, 0.0)'), hoverinfo = 'text') %>%
add_trace(y = dataset$TH , marker = list(color = ~colors), hoverinfo = "text",
text = Hover_Text ) %>%
layout(title = '',
xaxis = list(title = ""),
yaxis = list(title = ""),
barmode = 'stack',
margin = list(l = 50, r = 30, b = 50, t = 20),
showlegend = FALSE) %>%
add_annotations(text = dataset$TH,
x = dataset$SortedCategoryLabel,
y = dataset$end,
xref = "x",
yref = "y",
valign=vert.align, height=40,
font = list(family = 'Arial',
size = 14,
color = "black"),
showarrow = FALSE)
g