Modifying labels (x,y,z) in heatmap on plotly? - r

I want to rename labels in a heatmap. for example:
instead of the label says "x:", I want the label to say "Hour:"
instead of the label says "y:", I want the label to say "Day:"
Library(plotly)
p <- plot_ly(z = volcano, colors = colorRamp(c("red", "green")), type = "heatmap")
furthermore, it would be useful, for example if we use a transformation of data in order to intensify contrast, still the html interactive label show real data.
Example

What about
library(plotly)
dat <- expand.grid(x = 1:nrow(volcano), y = 1:ncol(volcano))
dat$z <- c(volcano)
plot_ly(height = 500) %>%
layout(autosize = FALSE,
xaxis=list(title = "Hour", titlefont = list(size=20)),
yaxis=list(title = "Day", titlefont = list(size=20))) %>%
add_trace(data = dat, x = ~x, y = ~y, z = ~z, type = "heatmap",
hoverinfo = 'text',
text = ~paste("Hour:", dat$x,
"<br> Day:", dat$y,
"<br> z:", dat$z))

Related

Adding Contour Lines to 3D Plots

I am working with the R programming language. I made the following 3 Dimensional Plot using the "plotly" library:
library(dplyr)
library(plotly)
my_function <- function(x,y) {
final_value = (1 - x)^2 + 100*((y - x^2)^2)
}
input_1 <- seq(-1.5, 1.5,0.1)
input_2 <- seq(-1.5, 1.5,0.1)
z <- outer(input_1, input_2, my_function)
plot_ly(x = input_1, y = input_2, z = z) %>% add_surface()
I am now trying to add "contour lines" to the above plot as shown below: https://plotly.com/r/3d-surface-plots/
I am trying to adapt the code from the "plotly website" to make these contours, but I am not sure how to do this:
Graph 1:
# This might have worked?
fig <- plot_ly(z = ~z) %>% add_surface(
contours = list(
z = list(
show=TRUE,
usecolormap=TRUE,
highlightcolor="#ff0000",
project=list(z=TRUE)
)
)
)
fig <- fig %>% layout(
scene = list(
camera=list(
eye = list(x=1.87, y=0.88, z=-0.64)
)
)
)
Graph 2:
# I don't think this worked?
fig <- plot_ly(
type = 'surface',
contours = list(
x = list(show = TRUE, start = 1.5, end = 2, size = 0.04, color = 'white'),
z = list(show = TRUE, start = 0.5, end = 0.8, size = 0.05)),
x = ~x,
y = ~y,
z = ~z)
fig <- fig %>% layout(
scene = list(
xaxis = list(nticks = 20),
zaxis = list(nticks = 4),
camera = list(eye = list(x = 0, y = -1, z = 0.5)),
aspectratio = list(x = .9, y = .8, z = 0.2)))
fig
Can someone please show me how to correctly adapt these above codes?
You were almost there.
The contours on z should be defined according to min-max values of z:
plot_ly(x = input_1, y = input_2, z = z,
contours = list(
z = list(show = TRUE, start = round(min(z),-2),
end = round(max(z),-2),
size = 100))) %>%
add_surface()
or automatically set by plotly :
plot_ly(x = input_1, y = input_2, z = z,
colors = 'Oranges',
contours = list(
z = list(show = TRUE))) %>%
add_surface()
The contour lines are on your plots, but may not be super visible due to the parameters in the contours.z list. Here's how you can tweak the contour lines to fit your needs:
fig <- plot_ly(z = ~z) %>% add_surface(
contours = list(
z = list(
show = TRUE,
# project=list(z=TRUE) # (don't) project contour lines to underlying plane
# usecolormap = TRUE, # (don't) use surface color scale for contours
color = "white", # set contour color
width = 1, # set contour thickness
highlightcolor = "#ff0000", # highlight contour on hover
start = 0, # include contours from z = 0...
end = 1400, # to z = 1400...
size = 100 # every 100 units
)
)
)
You can draw lines along the other dimensions by passing lists to x or y. (Per follow-up question from OP) you can change the surface color scale using colorscale, either specifying one of the named colorscale options or building your own. Example:
fig <- plot_ly(z = ~z) %>% add_surface(
colorscale = "Picnic",
contours = list(
x = list(show=TRUE, color="#a090b0", width=2, start=0, end=30, size=7.5),
y = list(show=TRUE, color="#a090b0", width=2, start=0, end=30, size=7.5),
z = list(show=TRUE, color="#a090b0", width=2, start=0, end=1400, size=300)
)
)

Making a predefined layout for plotly in R

I would like to make a predefined layout that I can use for my plot functions that I have created so as not to repeat myself everytime I make a plot. For example, I tried to do sth like the following which doesn't work and gives an error:
custom_layout <- function(){
plotly::layout(
xaxis = list(title = ""),
yaxis = list(title = ""),
title = list(text = title, y = 0.98)
)
}
plot_bar <- function(title, dt, x, y, fill){
plot_ly(dt, x = ~x, y = ~y, type = "bar",
color = ~ fill, split = ~ fill) %>%
custom_layout()}
plot_line <- function(title, dt, x, y, fill){
plot_ly(dt, x = ~x, y = ~y, type="scatter",
split = ~fill, mode="lines+markers") %>%
custom_layout()}
I call these 2 plotting functions multiple times in my code. I have also other predefined plotting functions like plot_line and plot_bar and I use the same layout for them as well but now manually adding the layout like in the following:
plot_bar <- function(title, dt, x, y, fill){
plot_ly(dt, x = ~x, y = ~y, type = "bar",
color = ~ fill, split = ~ fill) %>%
layout(
xaxis = list(title = ""),
yaxis = list(title = ""),
title = list(text = title, y = 0.98)
Ideally, I would like to define it like in the first scenario with a predefined layout that I could use later for every plotting function which is not working for me. Is there a way to do it with native plotly and not ggplot2?
You need to make the custom_layout() function take p as its first argument (just like layout() does).
library(tibble)
dt <- tibble(x=1:4, y=3:6, fill=1:4)
custom_layout <- function(p, title){
plotly::layout(p,
xaxis = list(title = ""),
yaxis = list(title = ""),
title = list(text = title, y = 0.98)
)
}
plot_bar <- function(title, dt, x, y, fill){
plot_ly(dt, x = ~x, y = ~y, type = "bar",
color = ~ fill, split = ~ fill) %>%
custom_layout(title=title)}
plot_bar(title="myplot", dt, "x", "y", "fill")

How to apply subplot to a list of plots with secondary y axis

I want to prepare a subplot where each facet is a separate dual y-axis plot of one variable against the others. So I make a base plot p and add secondary y-axis variable in a loop:
library(rlang)
library(plotly)
library(tibble)
dual_axis_lines <- function(data, x, y_left, ..., facets = FALSE, axes = NULL){
x <- rlang::enquo(x)
y_left <- rlang::enquo(y_left)
y_right <- rlang::enquos(...)
y_left_axparms <- list(
title = FALSE,
tickfont = list(color = "#1f77b4"),
side = "left")
y_right_axparms <- list(
title = FALSE,
overlaying = "y",
side = "right",
zeroline = FALSE)
p <- plotly::plot_ly(data , x = x) %>%
plotly::add_trace(y = y_left, name = quo_name(y_left),
yaxis = "y1", type = 'scatter', mode = 'lines',
line = list(color = "#1f77b4"))
p_facets <- list()
for(v in y_right){
p_facets[[quo_name(v)]] <- p %>%
plotly::add_trace(y = v, name = quo_name(v),
yaxis = "y2", type = 'scatter', mode = 'lines') %>%
plotly::layout(yaxis = y_left_axparms,
yaxis2 = y_right_axparms)
}
p <- subplot(p_facets, nrows = length(y_right), shareX = TRUE)
return(p)
}
mtcars %>%
rowid_to_column() %>%
dual_axis_lines(rowid, mpg, cyl, disp, hp, facets = TRUE)
However, the resulting plots have all the secondary y-axis variables cluttered in the first facet.
The issue seems to be absent when I return p_facets lists that goes into subplot as each plot looks like below:
How can I fix this issue?
Okay, I followed the ideas given in this github issue about your bug.
library(rlang)
library(plotly)
library(tibble)
dual_axis_lines <- function(data, x, y_left, ..., facets = FALSE, axes = NULL){
x <- rlang::enquo(x)
y_left <- rlang::enquo(y_left)
y_right <- rlang::enquos(...)
## I removed some things here for simplicity, and because we want overlaying to vary between subplots.
y_left_axparms <- list(
tickfont = list(color = "#1f77b4"),
side = "left")
y_right_axparms <- list(
side = "right")
p <- plotly::plot_ly(data , x = x) %>%
plotly::add_trace(y = y_left, name = quo_name(y_left),
yaxis = "y", type = 'scatter', mode = 'lines',
line = list(color = "#1f77b4"))
p_facets <- list()
## I needed to change the for loop so that i can have which plot index we are working with
for(v in 1:length(y_right)){
p_facets[[quo_name(y_right[[v]])]] <- p %>%
plotly::add_trace(y = y_right[[v]], x = x, name = quo_name(y_right[[v]]),
yaxis = "y2", type = 'scatter', mode = 'lines') %>%
plotly::layout(yaxis = y_left_axparms,
## here is where you can assign each extra line to a particular subplot.
## you want overlaying to be: "y", "y3", "y5"... for each subplot
yaxis2 = append(y_right_axparms, c(overlaying = paste0(
"y", c("", as.character(seq(3,100,by = 2)))[v]))))
}
p <- subplot(p_facets, nrows = length(y_right), shareX = TRUE)
return(p)
}
mtcars %>%
rowid_to_column() %>%
dual_axis_lines(rowid, mpg, cyl, disp, hp, facets = TRUE)
Axis text the same color as the lines.
For this you would need two things. You would need to give a palette to your function outside of your for-loop:
color_palette <- colorRampPalette(RColorBrewer::brewer.pal(10,"Spectral"))(length(y_right))
If you don't like the color palette, you'd change it!
I've cleaned up the for-loop so it's easier to look at. This is what it would now look like now so that lines and axis text share the same color:
for(v in 1:length(y_right)){
## here is where you can assign each extra line to a particular subplot.
## you want overlaying to be: "y", "y3", "y5"... for each subplot
overlaying_location = paste0("y", c("", as.character(seq(3,100,by = 2)))[v])
trace_name = quo_name(y_right[[v]])
trace_value = y_right[[v]]
trace_color = color_palette[v]
p_facets[[trace_name]] <- p %>%
plotly::add_trace(y = trace_value,
x = x,
name = trace_name,
yaxis = "y2",
type = 'scatter',
mode = 'lines',
line = list(color = trace_color)) %>%
plotly::layout(yaxis = y_left_axparms,
## We can build the yaxis2 right here.
yaxis2 = eval(
parse(
text = "list(side = 'right',
overlaying = overlaying_location,
tickfont = list(color = trace_color))")
)
)
}

How do I allow Plotly bar text to overflow past bar?

How do I get the text size for dr5 and dr3 for the shorter bars? If the text is longer than the bar span, I would like the text to overflow past the end of the bar.
I tried using uniformtext in layout, but that shrunk all text to the smallest font being used. How do I change all font to the biggest size being used?
library(plotly)
# Test long text and short bars
xValues <- c("loooooooooooooooooonnnnnngg","lonnnnnnnnnnggggggg",
"dr3","dr4","dr5")
yValues <- c(0.5,1,2,0.22,10)
bar <- plot_ly(x = yValues,
y = xValues) %>%
add_trace(
type = 'bar',
orientation = 'h',
text = xValues,
textangle = 360,
textposition = "inside",
insidetextanchor = "start",
showlegend = F) %>%
layout(
yaxis = list(zeroline = FALSE,showline = FALSE,showticklabels = FALSE),
uniformtext = list(mode = "show")
)
bar
This can be achieved by adding the labels via add_text like so:
BTW: I put the vectors inside a df. Seems more natural to me.
library(plotly)
# Test long text and short bars
xValues <- c("loooooooooooooooooonnnnnngg","lonnnnnnnnnnggggggg",
"dr3","dr4","dr5")
yValues <- c(0.5,1,2,0.22,10)
df <- data.frame(
x = xValues,
y = yValues
)
bar <- plot_ly(df, x = ~y, y = ~x, text = ~x) %>%
add_trace(
type = 'bar',
orientation = 'h',
showlegend = F) %>%
add_text(x = 0.1, textposition = "middleright") %>%
layout(yaxis = list(zeroline = FALSE,showline = FALSE, showticklabels = FALSE))
bar

How to create an Orbit Chart in R? (Plotly/ggplot2)

I have spent time researching with no direction on how to create an orbit chart
I would ideally like to be able to create interactive versions (such as Plotly) but a ggplot2 would suffice as well.
Any suggestions are much appreciated!
For a weekly vis contest some time ago, I created some charts like this. I think the commonly accepted term now is "connected scatterplot".
Here is the skeleton plotly code I used.
plot_ly(
df,
x = x_var,
y = y_var,
group = group_var,
mode = "markers") %>%
add_trace(
x = x_var,
y = y_var,
xaxis = list(title = ""),
yaxis = list(title = ""),
group = group_var,
line = list(shape = "spline"),
showlegend = FALSE,
hoverinfo = "none")
You can look at the github repo for my submission which includes the code for both ggplot and plotly to produce connected scatterplots.
Using ggplot2:
geom_path() connects the observations in the order in which they appear in the data. geom_line() connects them in order of the variable on the x axis.
Taken from the ggplot manual page: http://docs.ggplot2.org/current/geom_path.html
You may also try out geom_curve and geom_segment if you want more control.
Thanks to #Bishop, I was able to formulate something really close to my ideal orbit chat. I included some chart annotations, for the start and end date and a label for which direction is the optimal solution.
max_date <- final_data_grp[which.max(final_data_grp$week_num), ]
min_date <- final_data_grp[which.min(final_data_grp$week_num), ]
end <- list(
x = max_date$AreaWOH,
y = max_date$SLevel,
text = paste('End', max_date$MondayDate),
xref = "x",
yref = "y"
)
start <- list(
x = min_date$AreaWOH,
y = min_date$SLevel,
text = paste('Start', min_date$MondayDate),
xref = "x",
yref = "y"
)
best_label = list(
x = min(final_data_grp$AreaWOH),
y = max(final_data_grp$SLevel),
text = 'Best Scenario',
showarrow = FALSE,
bordercolor='#c7c7c7',
borderwidth=2,
borderpad=4,
bgcolor='#ff7f0e',
opacity=.7
)
plot_ly(
final_data_grp,
x = AreaWOH,
y = SLevel,
group = MondayDate,
showlegend = FALSE,
marker = list(size = 8,
color = 'black',
opacity = .6)) %>%
add_trace(
x = AreaWOH,
y = SLevel,
line = list(shape = "spline"),
hoverinfo = "none",
showlegend = FALSE) %>%
layout(annotations = list(start, end, best_label))

Resources