I'm trying to plot a network visualization using plotly in R. The nodes represent animals, and the edges represent connections between them. A smaller mock dataset is given for easy reproducibility
library(plotly)
library(dplyr)
node_positions <- read.csv(text = "x,y,id,GenomeName,color,GenomeType,sortit
4.28773954083886,-23.3166298876944,2079,Hedgehog,#BFB2B0,Reference,2
-4.56413366610378,-4.47975813907212,5667,Panda,#04A777,Q,1
18.8893915853008,-11.0146567520996,237,Koala,#FB8B24,H,1
-17.1774910942374,-12.6076416632838,3289,Fox,#BFB2B0,Reference,2
19.7055270823247,-10.2966406982056,288,Toucan,#FB8B24,H,1
-5.60179332195936,-8.14901724184661,5679,Orca,#04A777,Q,1
3.66449334853917,-10.841715127887,5750,Platypus,#F3D053,U,1
-4.71008202168981,7.80254488326493,137,Platypus,#D90368,E,1
-6.08198788807958,-3.53993778027834,5722,Hippo,#04A777,Q,1
-3.93629844321969,-22.7681051424,744,Cobra,#BFB2B0,Reference,2", stringsAsFactors = FALSE)
# Simulate an edges dataframe (normally from igraph)
edges_df <- data.frame(
from = sample(node_positions$id, 10, replace = TRUE),
to = sample(node_positions$id, 10, replace = TRUE)
)
# Join node positions
edges_df <- edges_df %>%
left_join(node_positions, by = c("from" = "id")) %>%
rename(x_start = x, y_start = y) %>%
left_join(node_positions, by = c("to" = "id")) %>%
rename(x_end = x, y_end = y)
fig <- plot_ly()
# Add edges (lines connecting nodes)
fig <- fig %>%
add_segments(
data = edges_df,
x = ~x_start, y = ~y_start,
xend = ~x_end, yend = ~y_end,
line = list(color = "#E3DDE4", width = 0.5),
hoverinfo = "none"
)
# Add nodes (scatter points with hover GenomeNames)
fig <- fig %>%
add_trace(
data = node_positions,
type = "scatter",
mode = "markers",
x = ~x, y = ~y,
marker = list(size = 9, color = ~I(as.character(node_positions$color))),
hoverinfo = "text",
hovertext = ~GenomeName,
hoverlabel = list(font = list(size = 12))
)
# Final Plotly adjustments
fig <- fig %>%
layout(
title = "Animals - 10 February 2025",
xaxis = list(title = "", showticklabel = FALSE, zeroline = FALSE),
yaxis = list(title = "", showticklabel = FALSE, zeroline = FALSE)
)
fig
Problem: Legend Not Showing or Colors Getting Reordered
Desired Outcome:
Show a legend where each GenomeType (Q,H,E, etc) has a correctly colored entry, which is visible in the plotly figure. I can also double dick
Ensure that colors stay consistent between the plot and the legend.
How can I fix this while keeping the correct colors and ensuring the legend displays properly?
You can achieve your desired result my "mapping" GeomType
on the color
attribute as you already tried and by passing a named vector of colors to the colors=
attribute in plotly()
. And just in case that you want a specific order you can do so by converting to a factor
:
library(plotly, warn = FALSE)
library(dplyr, warn = FALSE)
colors <- node_positions |>
distinct(GenomeType, color) |>
tibble::deframe()
node_positions$GenomeType <- factor(
node_positions$GenomeType,
names(colors)
)
fig <- plot_ly(
colors = colors
)
# Add edges (lines connecting nodes)
fig <- fig %>%
add_segments(
data = edges_df,
x = ~x_start, y = ~y_start,
xend = ~x_end, yend = ~y_end,
line = list(color = "#E3DDE4", width = 0.5),
hoverinfo = "none"
)
# Add nodes (scatter points with hover GenomeNames)
fig <- fig %>%
add_trace(
data = node_positions,
type = "scatter",
mode = "markers",
x = ~x, y = ~y, color = ~GenomeType,
marker = list(size = 9),
hoverinfo = "text",
hovertext = ~GenomeName,
hoverlabel = list(font = list(size = 12))
)
# Final Plotly adjustments
fig <- fig %>%
layout(
title = "Animals - 10 February 2025",
xaxis = list(title = "", showticklabel = FALSE, zeroline = FALSE),
yaxis = list(title = "", showticklabel = FALSE, zeroline = FALSE)
)
fig