I have created subplots in Plotly that each contain a bar chart (or boxplot) and three trace lines. I have created traces at y= 1,2,3 to act as ablines like in ggplot.
What the plots look like:
and
.
Problem:
I want to have it so the bars of the bar chart are in front of the trace lines so you should only be able to see the trace lines in between the bars.
My code currently:
(I have excluded the code that generates the subplots as I don't think it is needed)
generate_plotly_barPlot <- function(dat, showLeg, err) {
p <- plot_ly(x=dat$xVar, # Initialize graph with line y=2
y=2,
type="scatter",
mode="lines",
hoverinfo="none",
layer="below",
line=list(color="grey",
width=2),
showlegend=FALSE) %>%
# Add trace at line y=1
add_trace(x=dat$xVar,
y=1,
type="scatter",
mode="lines",
hoverinfo="none",
line=list(color="grey",
width=1.5,
dash="dot"),
inherit=FALSE,
showlegend=FALSE) %>%
# Add trace at line y=3
add_trace(x=dat$xVar,
y=3,
type="scatter",
mode="lines",
hoverinfo="none",
line=list(color="grey",
width=1.5,
dash="dot"),
inherit=FALSE,
showlegend=FALSE)%>%
# Create Bar Chart
add_trace(x=dat$xVar,
y=dat$CopyNumber,
type="bar",
mode="markers",
color=dat$fillColor,
orientation="v",
inherit=FALSE,
marker=list(opacity=1),
legendgroup=dat$xVar,
showlegend=showLeg,
error_y = list(value=dat[[err]],
color='#000000',
thickness=3,
width=6,
visible=TRUE))
My approach:
I thought that the order the traces were created would define which layer they would be on in the graph, so since I plotted the bar chart after all of the trace lines, it would sit above them.
I also tried creating shapes to be the ablinesbut it was really difficult to get them in the correct position for subplots. add_traces was my best approach. Shapes in plotly have a layer parameter to define whether to place the shape above or below (see the plotly reference). I was hoping there was something like this that applied to traces, but I couldn't find it.
Maybe this could help you started. You did not provide a data set so here is a small made-up example. You can use layout to add a shape (a line in your case) to your graphic. As you can see the bar is above the line. Hope it helps!
plot_ly() %>%
add_bars(x = c("giraffes", "orangutans", "monkeys"), y = c(20, 14, 23)) %>%
layout(shapes = list(list(type = "lines",x0 = -1, x1 = 3, xref = "x", y0 = 3, y1 = 3, yref = "y", layer = "below")))
Related
I'm trying to use R plotly's bar type plot to generate a plot with horizontally laid out boxes and add to that a horizontal line which is in their background (rather than goes on top of them). In addition, I would like the line to extend symmetrically one box unit in each direction.
Here's what I'm doing:
plot.df <- data.frame(x = paste0("LONG NAME ",1:6),y = 0.2,width=0.75,group = c("A","B","B","B","C","A"),stringsAsFactors = F)
plot.df$group <- factor(plot.df$group)
plotly::plot_ly(plot.df) %>%
plotly::add_trace(x=~x,y=~y/2,type='scatter',mode='lines',line=list(color='black'),showlegend=F) %>%
plotly::add_bars(x=~x,y=~y,width=~width,color=~group) %>%
plotly::layout(xaxis=list(title=NA,zeroline=F,tickangle=45),yaxis=list(title=NA,zeroline=F,showgrid=F,range=c(0,1),showticklabels=F))
Which gives:
My questions are:
How to extend the the line in both directions
How to put the line in the background so it does not run over the boxes
I specified plot.df$y as 0.2 but the yaxis range to be c(0,1) so that the boxes don't look like long bars. But then the legend appears too high. Any better way to get square boxes with the legend appearing lower than it currently is?
For the horizontal line you can see Horizontal/Vertical Line in plotly
with
layout(legend =list(x = 1 ,y =0 ))
you can solve the legend problem
I could not solve your second point (put the bar in the background). I hope it helps:
hline <- function(y = 0, color = "blue") {
list(
type = "line",
x0 = 0,
x1 = 1,
xref = "paper",
y0 = y,
y1 = y,
line = list(color = color)
)
}
plot_ly(plot.df) %>%
add_bars(x=~x,y=~y,width=~width,color=~group, hoverinfo = "text") %>%
layout(shapes = list(hline(0.1)))%>%
layout(legend =list(x = 1 ,y =0 ))%>%
layout(xaxis=list(title=NA,zeroline=F,tickangle=45),yaxis=list(title=NA,zeroline=F,showgrid=F,range=c(0,1),showticklabels=F))
I'm having trouble adding a title and legend to the inside of my graph. Is it not possible with tkplot OR plot?
dff <- data.frame(a = c(0,1,2,3,4),b = c(3,4,5,6,7))
nod <- data.frame(node = c(0:7),wt = c(1:8))
pg <- graph_from_data_frame(d = dff, vertices = nod,directed = F)
# plot function with edge.label added
tkplot(pg, edge.label = nod$wt, main = "this is my graph")
legend('topleft',legend= degree(pg)*5,pt.cex=20,col='white',
pch=21, pt.bg='white')
It doesn't seem to want to work the way I want it to. I just want the legend to show the vertices adjusted to be bigger for a higher degree.
I was also wondering if there is a way to plot only certain vertices from the graph? For example, you choose one vertex and plot only the vertices that form a path back to it?
Based on the help for tkplot, here's an example of how to add a title to an interactive plot:
library(tcltk)
id = tkplot(pg, edge.label = nod$wt, main = "this is my graph")
canvas = tk_canvas(id)
width = as.numeric(tkcget(canvas, "-width"))
height = as.numeric(tkcget(canvas, "-height"))
tkcreate(canvas, "text", width/2, 25, text="My title",
justify="center",
font=tkfont.create(family="helvetica", size=20, weight="bold"))
For the standard base R plot, your code works as is:
plot(pg, edge.label = nod$wt, main = "this is my graph")
legend('topleft',legend= degree(pg)*5,pt.cex=20,col='white',
pch=21, pt.bg='white')
I'd like to combine 2 different posts of mine - Set marker size based on coordinate values, not pixels, in plotly R - and - add_trace in plotly, which trace to use for my particular graph - into one here.
At a high level, I'd like to create interactive hexagonal heatmaps in R using plotly. I am considering the following two approaches:
using scatter trace with markers
using heatmap trace with hexagons
I am running into difficulties with both approaches. For the heatmap trace, I cannot find a parameter to change the shapes from squares to hexagons (does this exist?). For the scatter trace, I cannot fix the size of the markers to the values of the axes (only to pixel counts), and therefore the shapes do not scale the same size when I increase the size of the graph (see example at bottom).
and
Any thoughts on this would be appreciated!
EDIT: here's an example of my code using scatter trace with markers:
mydf <- data.frame(x = rep(1:20, times = 20), y = rep(1:20, each = 20),
thesize = 15)
plot_ly(mydf) %>%
add_trace(x = ~x, y = ~y, type = 'scatter', mode = 'markers',
marker = list(symbol = 'hexagon', size = ~thesize, opacity = 0.6))
# note that the size is 15 pixels. I'd prefer that the size is pinned to values on the X and/or Y axis.
Is it possible to add vertical line to a boxplot in plotly? I know it works in ggplot2, but I need it in plotly. Would be nice if I don't need to convert my static ggplot every time.
Here is a minimal example
plot_ly(x = ~rnorm(50), type = "box") %>%
add_trace(x = ~c(0.75),y=c(-2,0.5),type='scatter',mode='lines')
Instead of the line stoping before I want the line to go through the boxplot. In addition I want the same plot extent as the single boxplot.
Change the sequence of calls:
library(plotly)
plot_ly(x = ~c(0.75), y=c(-2,2), type='scatter', mode='lines') %>%
add_boxplot(x = ~rnorm(50), inherit = F) %>%
layout(yaxis = list(range = c(-2, 2)))
Here is some example code I wrote to illustrate my problem. Right now, the plot generates only the points. What I want to do is have horizontal lines that go through each point, spanning a length of 1 to each side. (i.e. for a point at (2,1) I want the line to run from (1,1) to (3,1)) How can I do this in plotly? I've looked here but can't seem to figure out how to get this to work when the y-axis is not numerical.
library(plotly)
p <- plot_ly(data = mtcars, x = ~mtcars$mpg, y = rownames(mtcars), type = 'scatter', mode = 'markers')
p
EDIT is the output from the code provided in the accepted answer (except showing all car names). I was wondering if there is a way to draw a horizontal line between each y-axis label, so that for example, between "Volvo 142E" and "Maserati Bora", a line separates them, and goes for the length of the plot. Right now, each horizontal line of the plot has a point on it. I want to separate each of those lines with another line.
To get this to work we had to replot the original scatter plot with an using the row index to prevent plotly from reordering cars. Then I added back to the axis labels.
library(plotly)
##I added the text argument(hover over text) so that I could make sure
##that the yaxis labels matched the points. feel free to delete.
p <- plot_ly(x = mtcars$mpg, y = seq_along(rownames(mtcars)), text=rownames(mtcars),
type = 'scatter', mode = 'markers')
##This sets some attributes for the yaxis. Note: in your origianl plot every other
##car name was shown on the y-axis so that is what I recreated but you could remove
##the "seq(1,32, by=2)" to show all car names.
ax <- list(
title = "",
ticktext = rownames(mtcars)[seq(1,32, by=2)],
tickvals = seq(1,32, by=2)
)
##This is taken from the plotly help page. y0 and y1 now are set to equal the row
##number and x0 and x1 are +/-1 from the car's mpg
line <- list(
type = "line",
line = list(color = "pink"),
xref = "x",
yref = "y"
)
lines <- list()
for (i in seq_along(rownames(mtcars))) {
line[["x0"]] <- mtcars$mpg[i] - 1
line[["x1"]] <- mtcars$mpg[i] + 1
line[c("y0", "y1")] <- i
lines <- c(lines, list(line))
}
p <- layout(p, title = 'Highlighting with Lines', shapes = lines, yaxis=ax)
p
Update based on OP's request.
To underline text in plotly use HTML tags. But <u> </u> does not work so we have to use <span> </span>...
ax2 <- list(
title = "", ticktext = paste0('<span style="text-decoration: underline;">',
rownames(mtcars)[1:32 %% 2 ==0],"</span>"),
tickvals = seq(1,32, by=2), style=list(textDecoration="underline"))