rggplot2colorsplotly

Plotly Legend Not Showing or Colors Getting Reordered in R


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

  1. Legend is missing: The plot does not show a legend for the nodes.
  2. Tried adding name = ~GenomeType, but then colors get randomly reassigned in the legend.

Desired Outcome:

  1. 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

  2. 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?

without name = ~GenomeType

with name = ~GenomeType


Solution

  • 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
    

    enter image description here