R Plotly: Connecting bars in waterfall chart - r

I'd like to create a waterfall chart similar to the one below in plotly with connecting bars between the waterfall segments, and it appears to be possible based on the below.
#would like a plot similar to this with connecting bars
library(waterfalls)
library(plotly)
waterfall(.data = data.frame(category = letters[1:5],
value = c(100, -20, 10, 20, 110)),
calc_total = T,
fill_by_sign = T)
#appears to be possible
p <- waterfall(.data = data.frame(category = letters[1:5],
value = c(100, -20, 10, 20, 110)),
calc_total = T,
fill_by_sign = T)
ggplotly(p)
Looking at the plotly graph it seems as if the letters labels are actually numbers(?). Though I'm not quite sure how to create the bar chart with number indices. Below is my try at getting it right. Could someone point me in the right direction here?
library(waterfalls)
library(plotly)
shap <- structure(list(values = c(5.82983875274658, 0, 0, 0, -0.0259701404720545, -0.103678397834301, -1.02624976634979, 0),
names = structure(1:8, .Label = c("bias", "speciessetosa", "speciesversicolor", "speciesvirginica", "sepal_width", "petal_width", "petal_length", "Ttl. Target Pred"), class = c("ordered", "factor")),
base = c(0, 5.82983875274658, 5.82983875274658, 5.82983875274658, 5.82983875274658, 5.80386861227453, 5.70019021444023, 0),
positive = c(5.82983875274658, 0, 0, 0, 0, 0, 0, 0),
negative = c(0, 0, 0, 0, -0.0259701404720545, -0.103678397834301, -1.02624976634979, 0),
shap_total = c(0, 0, 0, 0, 0, 0, 0, 4.67394044809043),
position = c(2.91491937637329, 5.82983875274658, 5.82983875274658, 5.82983875274658, 5.81685368251055, 5.75202941335738, 5.18706533126533, 2.33697022404522),
text_vals = c("5.83", "0", "0", "0", "-0.03", "-0.1", "-1.03", "4.67"), row_num = 1:8),
class = "data.frame", row.names = c(NA, -8L))
p <- plotly::plot_ly(shap, y = ~names, x = ~base, type = 'bar', marker = list(color = 'rgba(1,1,1, 0.0)')) %>%
add_trace(x = ~positive, marker = list(color = 'rgba(50, 171, 96, 0.7)',
line = list(color = 'rgba(50, 171, 96, 1.0)',
width = 2))) %>%
add_trace(x = ~negative, marker = list(color = 'rgba(219, 64, 82, 0.7)',
line = list(color = 'rgba(219, 64, 82, 1.0)',
width = 2))) %>%
add_trace(x = ~shap_total, marker = list(color = 'rgba(55, 128, 191, 0.7)',
line = list(color = 'rgba(55, 128, 191, 1.0)',
width = 2))) %>%
layout(title = 'SHAP Value Prediction Contributions',
xaxis = list(title = "Prediction Contribution"),
yaxis = list(title = ""),
barmode = 'stack',
showlegend = FALSE) %>%
add_annotations(text = ~text_vals,
y = ~names,
x = ~position,
xref = "x",
yref = "y",
font = list(family = 'Arial',
size = 12,
color = 'rgba(0, 0, 0, 1)'),
showarrow = FALSE)
p

Related

add trace in Plotly won't plot the right colour

I am trying to make a contour plot and draw a line on top of it (which I can do). I then overlaid two other lines using add_trace. For some reason the two lines I add using add_trace comes out orange instead of grey even though I specify grey (line = list(color = 'grey', )
I don't know how to add my data, it is very big. Is there any obvious reason as to why the colour changes to orange? If I change the width or the dash, it works. it just doesn't want to use the grey colour!
Thank you
(plot <- plot_ly(df, x = ~A, y = ~B, z = ~Difference, zauto = FALSE, zmin = -250, zmax = 250,
type="contour",
colorbar = list(title = "", titleside='right',
tickvals=c(-250, -200, -150, -100, -50, 0, 50, 100, 150, 200, 250), len = 1),
colorscale = "RdBu",
contours = list(start = 0, end = 0, coloring='heatmap', coloring='lines'),
line = list(color = 'black', width = 2)) %>%
add_trace(z = df$C, showscale = FALSE, line = list(color = 'grey', width = 2, dash = 'dash'), contours = list(start = 0, end = 0, coloring='lines')) %>%
add_trace(z = df$C, showscale = FALSE, line = list(color = 'grey', width = 2, dash = 'solid'), contours = list(start = 0, end = 0, coloring='lines')) %>%
layout(margin = list(l = 50, r = 70, b = 50, t = 50, pad = 4),
title = "", xaxis = x, yaxis = list(title = ""), font=t))
I guess the problem in your above code is, that you aren't specifiying the trace type. Accordingly plot_ly assumes that you are adding two more contour traces. Those traces are inheriting the colorscale you defined.
To avoid this you need to specify type = "scatter", mode = "lines", inherit = FALSE.
I made a simple example based on this.
library(plotly)
fig <- plot_ly(
x = c(-9, -6, -5, -3, -1),
y = c(0, 1, 4, 5, 7),
z = matrix(c(10, 10.625, 12.5, 15.625, 20, 5.625, 6.25, 8.125, 11.25, 15.625, 2.5, 3.125, 5, 8.125, 12.5, 0.625, 1.25, 3.125,
6.25, 10.625, 0, 0.625, 2.5, 5.625, 10), nrow = 5, ncol = 5),
type = "contour", colorbar = list(title = "", titleside='right'),
colorscale = "RdBu",
line = list(color = 'black', width = 2)) %>%
add_trace(x = -1:-7, y = 1:7, type = "scatter", mode = "lines", line = list(color = 'lightgreen', width = 2, dash = 'solid'), inherit = FALSE)
fig

R Highcharter Issues with adding plotBands on y-axis where hc_yAxis_multiples used

Trying to add plotBands w.r.t y-axis LHS, but getting errors
Error: All arguments must be named list
Example from the reference dataset:
library(highcharter)
library(dplyr)
df1 <- data.frame(month = c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"),
values1 = c(7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2,
26.5, 23.3, 18.3, 13.9, 9.6), stringsAsFactors = F)
df1$values2 <- df1$values1/5
Charts:
hc <- highchart() %>%
hc_yAxis_multiples(
list(lineWidth = 3),
list(showLastLabel = T, opposite = TRUE)) %>%
hc_title(text = "A nice chart") %>%
hc_chart(type = "column") %>%
hc_xAxis(categories = df1$month) %>%
hc_add_series(data = df1$values1) %>%
hc_add_series(data = df1$values2, type = "spline", color = "#1FA67A", yAxis = 1)
hc <- hc %>%
hc_tooltip(crosshairs = TRUE, shared = TRUE) %>%
hc_yAxis(minorGridLineWidth = 0, gridLineWidth = 0,
plotBands = list(
list(from = 10, to = 20, color = "rgba(68, 170, 213, 0.1)",
label = list(text = "A low band")),
list(from = 20, to = 25, color = "rgba(0, 0, 0, 0.1)",
label = list(text = "A medium band")),
list(from = 25, to = 30, color = "rgba(68, 170, 213, 0.1)",
label = list(text = "A high band"))
))
Since you used hc_yAxis_multiples, you should specify the configurations for each axis inside this list. When you call hc_yAxis again after this, it doesn't know which axis to put your plotBand etc..
Try something like this:
hc <- highchart() %>%
hc_yAxis_multiples(
list(lineWidth = 3,
minorGridLineWidth = 0,
gridLineWidth = 0,
plotBands = list(
list(from = 10, to = 20, color = "rgba(68, 170, 213, 0.1)",
label = list(text = "A low band")),
list(from = 20, to = 25, color = "rgba(0, 0, 0, 0.1)",
label = list(text = "A medium band")),
list(from = 25, to = 30, color = "rgba(68, 170, 213, 0.1)",
label = list(text = "A high band"))
)
),
list(minorGridLineWidth = 0,gridLineWidth = 0,
showLastLabel = T, opposite = TRUE)) %>%
hc_title(text = "A nice chart") %>%
hc_chart(type = "column") %>%
hc_xAxis(categories = df1$month) %>%
hc_add_series(data = df1$values1) %>%
hc_add_series(data = df1$values2, type = "spline", color = "#1FA67A", yAxis = 1)

Annotation / Text for ticklabels in R plotly polar chart

Let's say, I have a simple polar chart:
R code:
library(plotly)
p <- plot_ly(
type = 'scatterpolar',
r = c(0,1,2,4),
theta = c(0,45,90,120),
size = c(10, 20, 30, 40),
sizes = c(100, 300),
mode = 'markers'
) %>%
layout(
showlegend = FALSE,
polar = list(
angularaxis = list(
showticklabels = TRUE#,
#tickmode="array",
#tickvals = c(22.5, 67.5, 112, 157.5, 202, 247.5, 292, 337.5),
#ticktext = c('A', "B", "C", "D", "E", "F", "G", "H")
),
radialaxis = list(
tickmode="array",
tickvals = c(0, 1, 2, 3, 4, 5, 6, 7),
ticktext = c('', "One", "Two", "Three", "Four", "Five", "Six", "Seven")
)
)
)
ggplotly(p)
Chart plotted:
When I set showticklabels = FALSE, the angle tick labels disappears, and then I want to put A,B,C,D,E,F,G and H at angles c(22.5, 67.5, 112, 157.5, 202, 247.5, 292, 337.5).
I am not able to get the below expected plot using ticktexts and tickvals.
Can someone please help me with getting me to the solution, or if it is possible with add_text or add_annotation ?
Expected plot:
you could remove all grid lines altogether in the angularaxis with showgrid = FALSE, or you can have a line per 22.5 degree starting from 0 and then the ticktext would be something like this c('', 'A', '', 'B', '', 'C', .......) , or you could tediously add the lines you expect to have and then remove the grid lines like this:
p <- plot_ly() %>%
# data points
add_trace(type = 'scatterpolar',
r = c(0,1,2,4),
theta = c(0,45,90,120),
size = c(10, 20, 30, 40),
sizes = c(100, 300),
mode = 'markers') %>%
# straight line from 0 dg to 180 dg
add_trace(type = 'scatterpolar',
r = c(0,4.3,4.3),
theta = c(0, 180, 360),
mode = 'lines',
line = list(color = 'grey', width = 1)) %>%
# straight line from 45 dg to 225 dg
add_trace(type = 'scatterpolar',
r = c(0,4.3,4.3),
theta = c(0, 45, 225),
mode = 'lines',
line = list(color = 'grey', width = 1)) %>%
# straight line from 90 dg to 270 dg
add_trace(type = 'scatterpolar',
r = c(0,4.3,4.3),
theta = c(0, 90, 270),
mode = 'lines',
line = list(color = 'grey', width = 1)) %>%
# straight line from 135 dg to 315 dg
add_trace(type = 'scatterpolar',
r = c(0,4.3,4.3),
theta = c(0, 135, 315),
mode = 'lines',
line = list(color = 'grey', width = 1)) %>%
# fill circle of radius 1
add_trace(type = 'scatterpolar',
mode = 'lines',
r = 1,
theta =seq(0, 360, 0.1),
line = list(color = 'grey'),
fill = 'toself',
fillcolor = 'grey',
opacity = 0.5) %>%
layout(
showlegend = FALSE,
polar = list(
angularaxis = list(
showticklabels = TRUE,
# remove grid lines and ticks
showgrid = FALSE,
ticks = '',
# if you want the axis to go the other way around
# direction = 'clockwise',
tickmode="array",
tickvals = seq(22.5, 337.5, 45),
ticktext = LETTERS[1:8]
),
radialaxis = list(
tickmode="array",
tickvals = c(0, 1, 2, 3, 4, 5, 6, 7),
ticktext = c('', "One", "Two", "Three", "Four", "Five", "Six", "Seven")
)
)
)
ggplotly(p)
Output chart:
I noticed that the expected output you have there, lists the letters the other way around as you have them in your code. If this is something you also want just change the order of the letters to match the angles like this c("A", "H", "G", "F", "E", "D", "C", "B") (reversed order starting from A)

R Plotly-plot layout (margind and x axis on the top)

I encountered a problem while using plotly and R shiny to visualize data. My sample codes are:
y <- c("q1", "q2", "q3", "q4", "q5", "q6", "q7")
x1 <- c(20, 10, 15, 15, 20, 10, 15)
x2 <- c(10, 20, 20, 10, 10, 30, 10)
x3 <- c(10, 10, 5, 10, 10, 5, 5)
x4 <- c(20, 25, 25, 35, 55, 40, 35)
x5 <- c(40, 35, 35, 30, 5, 15, 35)
num <- c(1,3,5,6,7,2,4)
df <- data.frame(y, x1, x2, x3, x4, x5, num)
plot_ly(df[order(-xtfrm(df$num)),]) %>%
add_trace(x = ~x1, y = ~y, marker = list(color = 'rgb(202,0,32)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x2, y = ~y, marker = list(color = 'rgb(244,165,130)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x3, y = ~y, marker = list(color = 'rgb(223,223,223)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x4, y = ~y, marker = list(color = 'rgb(146,197,222)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x5, y = ~y, marker = list(color = 'rgb(5,113,176)'), type = 'bar', orientation = 'h') %>%
layout(title="mytitle",
xaxis = list(title = "",
showticklabels = TRUE,
zeroline = FALSE,
domain = c(0.15, 1)),
yaxis = list(title = "",
showticklabels = FALSE,
zeroline = FALSE,
categoryorder = 'array',
categoryarray = ~qt),
barmode = 'relative',
paper_bgcolor = 'rgb(248, 248, 255)', plot_bgcolor = 'rgb(248, 248, 255)',
autosize=T,
margin = list(l = 150, r = 10, t = 100, b = 50, pad=4),
showlegend=F) %>%
# labeling the y-axis
add_annotations(xref = 'paper', yref = 'y', x = 0.14, y = df$y,
xanchor = 'right',
text = df$y,
font = list(family = 'Arial', size = 5,
color = 'rgb(67, 67, 67)'),
showarrow = FALSE, align = 'right')
The problem is that the margins does not work very well with large amount of questions. In my data, one of the categories includes more than 40 questions. The plot with 5 questions looks fine. (length=500)
But the plot with over 40 questions have big top and bottom margins. (length=4000)
Please help me get rid of these weird margins.
Also, I'd like to know how to put the x-axis on both the top and bottom of the plot. Thank you!

plotly-Sort yaxis alphabetically

I'm looking for a way to sort my plotly bar plot by yaxis alphabetically. I tried several ways but the order of y is still from z to a, instead of a to z. Please help me out!
qt <- c("A", "C", "B","B","A", "C", "C")
y <- c("q1", "q2", "q3", "q4", "q5", "q6", "q7")
x1 <- c(20, 10, 15, 15, 20, 10, 15)
x2 <- c(10, 20, 20, 10, 10, 30, 10)
x3 <- c(10, 10, 5, 10, 10, 5, 5)
x4 <- c(20, 25, 25, 35, 55, 40, 35)
x5 <- c(40, 35, 35, 30, 5, 15, 35)
df <- data.frame(qt, y, x1, x2, x3, x4, x5)
df$qt <- factor(df$qt, levels = c("A", "B", "C"))
plot_ly(df) %>%
add_trace(x = ~x1, y = ~y, marker = list(color = 'rgb(202,0,32)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x2, y = ~y, marker = list(color = 'rgb(244,165,130)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x3, y = ~y, marker = list(color = 'rgb(223,223,223)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x4, y = ~y, marker = list(color = 'rgb(146,197,222)'), type = 'bar', orientation = 'h') %>%
add_trace(x = ~x5, y = ~y, marker = list(color = 'rgb(5,113,176)'), type = 'bar', orientation = 'h') %>%
layout(title="mytitle",
xaxis = list(title = "",
showticklabels = TRUE,
zeroline = FALSE,
domain = c(0.15, 1)),
yaxis = list(title = "",
showticklabels = FALSE,
zeroline = FALSE),
barmode = 'relative',
paper_bgcolor = 'rgb(248, 248, 255)', plot_bgcolor = 'rgb(248, 248, 255)',
autosize=T,
margin = list(l = 150, r = 50, t = 100, b = 50),
showlegend=F) %>%
# labeling the y-axis
add_annotations(xref = 'paper', yref = 'y', x = 0.14, y = df$y,
xanchor = 'right',
text = df$y,
font = list(family = 'Arial', size = 15,
color = 'rgb(67, 67, 67)'),
showarrow = FALSE, align = 'right')%>%
#labeling the y-axis (category)
add_annotations(xref = 'paper', yref = 'qt', x = 0.01, y = df$y,
xanchor = 'right',
text = df$qt,
font = list(family = 'Arial', size = 15,
color = 'rgb(67, 67, 67)'),
showarrow = FALSE, align = 'right')
The primary goal I would like to accomplish is to order this by the variable qt (from A to C). But if this is impossible, ordering the plot by y is also desirable (from q1 to q7). My plot looks like this:
Thank you in advance!

Resources