Change legend size in plotly chart - r

Is there a way to change the legend size in plotly for R? I have not come across this option. I have looked at the docs on legends, https://plot.ly/r/legend/, but it does not mention this.

Use layout(legend = list(font = list(size(30)))):
plot_ly(data = mtcars, x = as.character(mtcars$cyl),
y = mtcars$mpg, type = "box", color = as.character(mtcars$cyl)) %>%
layout(showlegend = TRUE, legend = list(font = list(size = 30)))

While working with legends, there are two pieces to configure.
Legend title (legend_title parameter)
Actual legend (legend parameter)
Let's say you already have a fig(it can be mostly any plot), to that add below line with parameters as you wish, in separate dictionaries.
fig.update_layout(legend = dict(font = dict(family = "Courier", size = 50, color = "black")),
legend_title = dict(font = dict(family = "Courier", size = 30, color = "blue")))
This way you will have more control over two thing.

Related

Scale command not applied to plot

The scale does not change the way I want and the way I wrote in the code. Why is that? Can someone help? My goal is to have a tick and label for every year on the x axis and a scale from -6 to 3 on the y axis, also including ticks and labels.
Periode <- as.Date(website$Datum)
Index <- website$KonSens
datebreaks <- seq(as.Date("1998-03-31"), as.Date("2022-06-30"), by = "1 month")
plot.Website <-
ggplot(data = website, aes(x = Periode, y = Index)) +
scale_x_date(breaks = datebreaks) +
scale_y_continuous(breaks = seq(-6,3,1), labels = c("-6", "-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3"), limits = c(-6,4), n.breaks = 10)+
theme(axis.text = element_text(color = "black", face = "bold", size = 10),
axis.line.y = element_line(color = "black", size = 2),
axis.line.x = element_blank(),
axis.title = element_text(color = "black", face = "bold"),
axis.title.y = element_text(angle = 180)) +
geom_line(aes(y = Index), color = "#7AA489",size = 1.5) +
geom_point(shape = 21, color = "#003478", fill = "#7AA489", size = 2.5, stroke = 1)
ggplotly(plot.Website, dynamicTicks = TRUE) %>%
rangeslider(borderwidth = 1)
Plotly may ignore you regardless of what you do because it looks like you are asking for almost 300 tick labels on the x-axis. However, when you use ggplotly, date fields become character fields. (I don't know if this is from ggplot or if it's a Plotly-ism.)
After rendering the ggplotly object, you can replace the x in each trace and replace the majority of the arguments for layout.xaxis. Alternatively, you may find it to be a lot easier if you create this in Plotly, to begin with.
I've added the data I used because your question is not reproducible. It looks like you're new to SO; welcome to the community! If you want great answers quickly, it's best to make all questions reproducible. For example, sample data from the output of dput() or reprex::reprex(). Check it out: making R reproducible questions.
In the following code, the only parts you need to create the plot without the aesthetics are the first two piped: plot_ly() and add_lines().
I added comments to explain what different aspects of this code is doing. Additionally, I've broken down some of this a bit further after the code and plot image.
library(tidyverse)
library(plotly)
# Periode <- as.Date(website$Datum) # data not provided
# Index <- website$KonSens
set.seed(353)
website <- data.frame(
Periode = sample(seq(as.Date("1998-03-31"), as.Date("2022-06-30"), by = "week"), 50),
Index = sample(runif(100, -4.5, 2.5), 50)) %>%
arrange(Periode)
plot_ly(type = "scatter", mode = "markers",
marker = list(color = "#7AA489", size = 8,
line = list(width = 2, color = "#003478")),
data = website, x = ~Periode, y = ~Index) %>%
add_lines(line = list(width = 5, color = "#7AA489")) %>%
layout(xaxis = list(dtick = "M18", # every 18 months
tickformat = "%b %Y"), # Abbrev Month, 4-digit year
yaxis = list(range = c(-6, 3), # show this range
zeroline = F, # remove horizontal line at 0
showline = T), # vertical line along y-axis
showlegend = F) %>% # no legend
htmlwidgets::onRender("function(el, x){. # make the axis titles BOLD
gimmeX = document.querySelector('g.infolayer g.g-xtitle text');
gimmeY = document.querySelector('g.infolayer g.g-ytitle text');
gimmeX.style.fontWeight = 'bold';
gimmeY.style.fontWeight = 'bold';
}") %>%
rangeslider(borderwidth = 1)
Specifying the Range on the y-axis
In Plotly, you won't need to set breaks and labels. You just need to define the range. If that's all you designated in the layout, it would like something like this.
layout(yaxis = list(range = c(-6, 3))
Non-Dynamic Date x-axis Tick Text Formatting
Labels on the x-axis can be specified to be labeled by month. However, like a commenter mentioned, you loose the dynamic date scaling done when you zoom. You can actually set the scaling date format for zooming ranges, as well. (I won't go into that in this answer, though.)
To specify the labels on the x-axis as every month by month, you would use layout.xaxis.dtick = "M1", every 18 months is M18, and so on. If you wanted to specify the appearance as the month and year, you can use the same formatting as used in as.Date, where %b is an abbreviated month name, and %Y is a four-digit year. If this was all you needed to set in the layout, it would look like this.
layout(xaxis = list(dtick = "M18", # every 18 months
tickformat = "%b %Y")) # Abbrev Month, 4-digit year
Bold Axis Labels
Additionally, there isn't a parameter you can set to make the axis labels bold. It doesn't really matter if it's ggplotly or plot_ly.
However, you can use htmlwidgets::onRender to make this happen.
htmlwidgets::onRender("function(el, x){
gimmeX = document.querySelector('g.infolayer g.g-xtitle text');
gimmeY = document.querySelector('g.infolayer g.g-ytitle text');
gimmeX.style.fontWeight = 'bold';
gimmeY.style.fontWeight = 'bold';
}")

Plot colors change when exporting as SVG file in R

I am generating a figure for publishing that includes a heatmap and when I export it as .svg the colors change.
When I visualize it in R the colors look ok (heatmap colors match the legend colors):
However, after exporting it to svg the colors in the heatmap look dimmer:
I think it has something to do with the svg device including a "white border" to every row of the heatmap, as the colors in the legend are unaffected. If you zoom in very closely you can appreciate it:
I am using the following code to export them. I have tried changing the bg and antialias parameteres of svg but there is no change:
svg(filename="test.svg",width = 10, height = 5)
Figure3
dev.off()
When I export is as pdf, the colors are ok:
I guess I will export them as .pdf but I would like to know what is causing this more as a curiosity.
Thanks!
Edit: added dataset and code to generate the plot:
From the package documentation, default colors for the heatmap are generated as:
colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"))
For the blocks in the left I used another palette in the initial example, here I use RColorBrewer and it has the same effect.
I dont think it's a problem of the color palette as it is ok in the legend, I guess it's a problem of a "border" around each row (both the blocks and the heatmap colors are defined as rows of a tile).
Dataset:
https://file.io/l6fL28Cy
Code:
library(ComplexHeatmap)
library(RColorBrewer)
Import data:
x = readRDS("data.rds")
#Select number of clusters to plot:
clusters = 7
#Generate dendrogram to make block annotation:
dend = as.dendrogram(hclust(as.dist(1- cor(t(x))),"complete"), hang=-1)
#Create annotation block for heatmap
cl_num = cutree(dend, k = clusters)
cl_col = brewer.pal(clusters,"Set2")
names(cl_col) = unique(cl_num)
cl_col = list(cl_num=cl_col)
row_ha = rowAnnotation(cl_num = cl_num,
col = cl_col,
annotation_legend_param = list(title = "Cluster"),
show_annotation_name = F)
###Create heatmap:
Heatmap(x,
clustering_distance_columns = "euclidean",
clustering_method_columns = "complete",
clustering_distance_rows = "pearson",
clustering_method_rows = "complete",
row_split = clusters,
left_annotation = row_ha,
show_row_names = F,
heatmap_legend_param = list(title = "Z-score"),
column_title = "Treatment",
row_title = "Genes",
use_raster = F,
column_dend_height = unit(0.1, "cm"),
column_names_gp = gpar(fontsize = 16),
column_names_rot = 0,
column_names_centered = TRUE)

Is it possible to combine the ggplot legend with the plotly legend so they are equivalent?

I'm trying to combine ggplot and plotly together to make a timeline.
It's working great, but have an issue using the legend. The code below replicates what I'm trying to do.
library(ggplot2)
library(plotly)
x=1:10
df2 = data.frame(x,y = 2*x+rnorm(length(x)),lab = as.factor(c("col1","col2")))
status_colors <- c("#0070C0", "#00B050", "#FFC000", "#C00000","darkgreen","purple","darkgrey","blue","salmon","darkorange","black","navy","darkblue")
status_levels <- c(sort(unique(df2$lab)))
p= ggplot(df2,aes(x=x, y=y, col = lab)) + geom_point() + labs(col="labtest") +
scale_color_manual(values=status_colors,
labels=status_levels, drop = FALSE)
fig = ggplotly(p, tooltip = NULL)
fig %>%
add_text(
x = df2$x,
y = ifelse(df2$y>0,df2$y+0.05,df2$y-0.05),
text = df2$lab,
hovertext = df2$lab,
hoverinfo = 'text',
mode ="text",
textfont = list(color=status_colors[df2$lab], size =10),
marker = list(color=status_colors[df2$lab], size = 0.00001),
showlegend = T,
textposition = ifelse(df2$y>0,"top center","bottom center")
)
Basically, as you can see in the image, the label of each point is the same colour as the point that it is attached to. But whenever I add the legend of the label text from plotly, there is a new legend that appears that controls all the points regardless of their colour.
Thus, is there a way to combine the ggplot legend with the plotly legend so that it's only written col1 and col2 with the right colour and that whenever I interact with the points of a certain colour, the label attached to it stays there?
In other words, is there a way to remove the "trace 2" legend and make the "add_text" know that there is a legend already created in ggplot?
If I got you right, besides getting rid of the second legend (which can be simply achievd by setting showlegend = FALSE) you want one legend to control both the points and the labels. This can be achieved via legendgroups. Instead of adding labels with one add_text you could (or have to? Sorry. Still a plotly newbie so perhaps there is a simpler approach) add the labels via two add_text calls one for each col. Instead of copy and paste (which is probably okay for just two cols, but with more cols ...) you can add these via the magic of purrr::reduce to the ggplotly object. Try this:
library(ggplot2)
library(plotly)
library(purrr)
x=1:10
df2 = data.frame(x,y = 2*x+rnorm(length(x)),lab = as.factor(c("col1","col2")))
status_colors <- c("#0070C0", "#00B050", "#FFC000", "#C00000","darkgreen","purple","darkgrey","blue","salmon","darkorange","black","navy","darkblue")
status_levels <- c(sort(unique(df2$lab)))
p= ggplot(df2,aes(x=x, y=y, col = lab)) + geom_point() +
labs(col="labtest") +
scale_color_manual(values=status_colors,
labels=status_levels, drop = FALSE)
fig = ggplotly(p, tooltip = NULL)
purrr::reduce(c("col1", "col2"), ~ .x %>% add_text(
data = filter(df2, lab == .y),
x = ~x,
y = ~ifelse(y > 0, y + 0.05, y-0.05),
text = ~lab,
hovertext = ~lab,
hoverinfo = 'text',
mode ="text",
textfont = list(color= ~status_colors[lab], size =10),
marker = list(color= ~status_colors[lab], size = 0.00001),
showlegend = FALSE,
textposition = ~ifelse(y>0, "top center","bottom center"),
legendgroup = .y
), .init = fig)
BTW: I also simplified the code a little bit. You don't need df2$... because (gg)plotly already knows the data.

Boxplot next to a scatterplot in R with plotly

I created a scatter plot with plotly in R. Now I want to plot a boxplot with different data next to the scatter plot. I want to use plotly for this.
The result should look like this. Can someone help me please, I have no idea how to do that.
My code so far is
plot_ly(ds, x = ~x, y = ~y , mode = "markers", name = "Clusters", opacity = point.opacity,
text = ds$id,
hoverinfo = "text",
marker = list(symbol = point.symbol, color = ~color, size = point.size,
line = list(color = "#262626", width = point.linewidth, opacity = point.lineopacity)),
showlegend = F)
Here is an example on how to make a scatter with marginal box plots with plotly:
library(plotly)
data(iris)
create, three plots for the data: one for the scatter, two for the appropriate box plots, and one additional empty plot. Use the subplot function to arrange them:
subplot(
plot_ly(data = iris, x = ~Petal.Length, type = 'box'),
plotly_empty(),
plot_ly(data = iris, x = ~Petal.Length, y = ~Petal.Width, type = 'scatter',
mode = 'markers'),
plot_ly(data = iris, y = ~Petal.Width, type = 'box'),
nrows = 2, heights = c(.2, .8), widths = c(.8,.2), margin = 0,
shareX = TRUE, shareY = TRUE) %>%
layout(showlegend = F)

Scaling points and choosing colors with plot_ly R package

I have just started using plotly in R and it is working great but I cannot figure out how to do two things.
1) I need to pick the colors of my split. Currently, I am splitting by Territory and plotly doesn't allow me to code what colors I want each territory to be.
2) I also need to scale the points so that some markers are very large. I tried creating a size for each row and setting size = ~size and sizes = c(2, 100) but this did not work.
Any advice on how to do this? I've tried reading the plotly R reference guide but cannot figure out how to do this with plotly_mapbox. I've pasted my code without the size or color attempt because I could never get it to work.
p <- df %>%
plot_mapbox(lat = ~lat, lon = ~lon,
split = ~Territory,
mode = 'scattermapbox',
text = df$text,
hoverinfo = "text"
) %>%
layout(title = 'Ship to Zip Codes',
font = list(color='white'),
plot_bgcolor = '#191A1A',
paper_bgcolor = '#191A1A',
mapbox = list(style = 'dark'),
legend = list(orientation = 'h',
font = list(size = 8)),
margin = list(l = 25, r = 25,
b = 25, t = 25,
pad = 2))
You can set the marker size via marker = list(size = 2).
Setting the colors is more tricky and cannot be done directly with plot_mapbox as far as I know.
But we can assign a new column to our data frame
df$colors <- factor(df$class, levels = unique(df$class))
then define our own color list
cols <- c("red", "blue", "black", "green", "orange", "cyan", "gray50")
and finally plot everything via plot_geo
plot_geo(df) %>%
add_markers(
x = ~reclong, y = ~reclat, color = ~colors, colors = cols, marker = list(size = 2))
The whole code to get the custom colors in a scatter map in Plotly.
library(plotly)
df = read.csv('https://raw.githubusercontent.com/bcdunbar/datasets/master/meteorites_subset.csv')
df$colors <- factor(df$class, levels = unique(df$class))
cols <- c("red", "blue", "black", "green", "orange", "cyan", "gray50")
plot_geo(df) %>%
add_markers(x = ~reclong,
y = ~reclat,
color = ~df$colors,
colors = cols,
marker = list(size = 2))

Resources